Codebase list dillo / upstream/3.0.2_rc1
Imported Upstream version 3.0.2~rc1 Axel Beckert 12 years ago
76 changed file(s) with 2862 addition(s) and 1367 deletion(s). Raw diff Collapse all Expand all
7373
7474 Contributions are always welcome!
7575
76
77
78 ---------------
79 Non-Dillo code:
80 ---------------
81
82 * dw/fltkcomplexbutton.(cc|hh) contain code from the FLTK project whose
83 copyright is held by Bill Spitzak and others.
84 * src/binaryconst.h contains code by Tom Torfs that the author placed in the
85 public domain.
86 * src/md5.[ch] contain code by L. Peter Deutsch whose copyright is held by
87 Aladdin Enterprises.
00 =============================================================================
11 Dillo project
22 =============================================================================
3
4 Here we list changes that are relatively significant and/or visible to the
5 user. For a history of changes in full detail, see our Mercurial repository
6 at http://hg.dillo.org/dillo
7
8
9 dillo-3.0.2 [December 05, 2011]
10
11 +- Digest authentication
12 Patch: Justus Winter, corvid
13 +- text-transform property
14 - If not following redirection, show body of redirecting page.
15 - Middle click on stylesheet menu item opens in new tab/window.
16 - Improve handling of combining characters.
17 - Locale-independent ASCII character case handling (fixes Turkic locales).
18 Patches: corvid
19 +- Rework line breaking and fix white-space:nowrap handling.
20 Patch: Johannes Hofmann
21 +- Bind Ctrl-{PageUp,PageDown} to tab-{previous,next}.
22 Patch: Jeremy Henty
23
24 -----------------------------------------------------------------------------
325
426 dillo-3.0.1 [September 21, 2011]
527
5173 Patch: Johannes Hofmann
5274 +- Default binding for left-tab changed to Shift-Ctrl-Tab.
5375 Patch: Jeremy Henty
54
55 Note: these are user-visible changes. The full Changelog is kept
56 in our Mercurial repository at http://hg.dillo.org/dillo
57
5876
5977 -----------------------------------------------------------------------------
6078
11 Dillo web browser
22 ===================
33
4 Dillo-3.0 is the first release of the newest branch, which is
5 based on the already released fltk-1.3 toolkit. This is big news
6 because it clears the way for Dillo to return to those
7 distributions which had excluded Dillo2 due to FLTK2 never
8 being officially released.
4 Dillo is a multi-platform graphical web browser, known for its
5 speed and small footprint, that is developed with a focus on
6 personal security and privacy.
97
10 The development effort shifted to the dillo-3.x branch long ago,
11 and it became the active one; dillo-2.x received less and less
12 attention, and dillo-2.2.1 became the last of its series.
8 The dillo3 series uses version 1.3.x of the FLTK GUI toolkit
9 (http://fltk.org).
1310
14 The core team will focus on implementing the CSS feature of
15 floating elements. This will greatly improve dillo's web page
16 rendering since many sites have adopted floats instead of tables.
17
18 The new dillo3 has shown excellent stability.
11 The core team currently plans to focus on implementing the CSS
12 feature of floating elements. This will greatly improve
13 dillo's web page rendering since many sites have adopted floats
14 instead of tables.
1915
2016 The core team welcomes developers willing to join our workforce.
2117
2218
2319 NOTE: With FLTK-1.3, when running on X with Xft enabled (the
24 default), font naming is more restricted than it was with FLTK2.
25 If your font_* preferences are no longer working well, please try
26 the fc-list command as given in dillorc.
20 default), font naming is more restricted than it was with FLTK2
21 as used by dillo2. If your font_* preferences are no longer
22 working well, please try the fc-list command as it is shown in
23 dillorc.
2724
2825
2926 Here's a list of some old well-known problems of dillo:
3330
3431
3532 -------
36 FLTK1.3
33 FLTK-1.3
3734 -------
3835
3936 You can get FLTK-1.3 here:
5855
5956 2.- Then dillo3:
6057
61 tar jxvf dillo-3.0.1.tar.bz2
62 cd dillo-3.0.1
58 tar jxvf dillo-3.0.2.tar.bz2
59 cd dillo-3.0.2
6360 ./configure; make
6461 sudo make install-strip
6562
00 #! /bin/sh
11 # Attempt to guess a canonical system name.
22 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3 # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
3 # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
44 # Free Software Foundation, Inc.
55
6 timestamp='2009-12-30'
6 timestamp='2009-11-20'
77
88 # This file is free software; you can redistribute it and/or modify it
99 # under the terms of the GNU General Public License as published by
5555 GNU config.guess ($timestamp)
5656
5757 Originally written by Per Bothner.
58 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
59 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
60 Software Foundation, Inc.
58 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
59 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
6160
6261 This is free software; see the source for copying conditions. There is NO
6362 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
00 #! /bin/sh
11 # Configuration validation subroutine script.
22 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3 # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
3 # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
44 # Free Software Foundation, Inc.
55
6 timestamp='2009-12-31'
6 timestamp='2009-11-20'
77
88 # This file is (in principle) common to ALL GNU software.
99 # The presence of a machine in this file suggests that SOME GNU software
7474 version="\
7575 GNU config.sub ($timestamp)
7676
77 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
78 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
79 Software Foundation, Inc.
77 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
78 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
8079
8180 This is free software; see the source for copying conditions. There is NO
8281 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
14351434 -dicos*)
14361435 os=-dicos
14371436 ;;
1438 -nacl*)
1439 ;;
14401437 -none)
14411438 ;;
14421439 *)
00 #! /bin/sh
11 # Guess values for system-dependent variables and create Makefiles.
2 # Generated by GNU Autoconf 2.68 for dillo 3.0.1.
2 # Generated by GNU Autoconf 2.68 for dillo 3.0.2.
33 #
44 #
55 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
556556 # Identity of this package.
557557 PACKAGE_NAME='dillo'
558558 PACKAGE_TARNAME='dillo'
559 PACKAGE_VERSION='3.0.1'
560 PACKAGE_STRING='dillo 3.0.1'
559 PACKAGE_VERSION='3.0.2'
560 PACKAGE_STRING='dillo 3.0.2'
561561 PACKAGE_BUGREPORT=''
562562 PACKAGE_URL=''
563563
12861286 # Omit some internal or obsolete options to make the list less imposing.
12871287 # This message is too long to be a string in the A/UX 3.1 sh.
12881288 cat <<_ACEOF
1289 \`configure' configures dillo 3.0.1 to adapt to many kinds of systems.
1289 \`configure' configures dillo 3.0.2 to adapt to many kinds of systems.
12901290
12911291 Usage: $0 [OPTION]... [VAR=VALUE]...
12921292
13571357
13581358 if test -n "$ac_init_help"; then
13591359 case $ac_init_help in
1360 short | recursive ) echo "Configuration of dillo 3.0.1:";;
1360 short | recursive ) echo "Configuration of dillo 3.0.2:";;
13611361 esac
13621362 cat <<\_ACEOF
13631363
14631463 test -n "$ac_init_help" && exit $ac_status
14641464 if $ac_init_version; then
14651465 cat <<\_ACEOF
1466 dillo configure 3.0.1
1466 dillo configure 3.0.2
14671467 generated by GNU Autoconf 2.68
14681468
14691469 Copyright (C) 2010 Free Software Foundation, Inc.
21712171 This file contains any messages produced by compilers while
21722172 running configure, to aid debugging if configure makes a mistake.
21732173
2174 It was created by dillo $as_me 3.0.1, which was
2174 It was created by dillo $as_me 3.0.2, which was
21752175 generated by GNU Autoconf 2.68. Invocation command line was
21762176
21772177 $ $0 $@
30983098
30993099 # Define the identity of the package.
31003100 PACKAGE='dillo'
3101 VERSION='3.0.1'
3101 VERSION='3.0.2'
31023102
31033103
31043104 cat >>confdefs.h <<_ACEOF
69836983 # report actual input values of CONFIG_FILES etc. instead of their
69846984 # values after options handling.
69856985 ac_log="
6986 This file was extended by dillo $as_me 3.0.1, which was
6986 This file was extended by dillo $as_me 3.0.2, which was
69876987 generated by GNU Autoconf 2.68. Invocation command line was
69886988
69896989 CONFIG_FILES = $CONFIG_FILES
70497049 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
70507050 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
70517051 ac_cs_version="\\
7052 dillo config.status 3.0.1
7052 dillo config.status 3.0.2
70537053 configured by $0, generated by GNU Autoconf 2.68,
70547054 with options \\"\$ac_cs_config\\"
70557055
00 dnl Process this file with aclocal, autoconf and automake.
11
2 AC_INIT([dillo], [3.0.1])
2 AC_INIT([dillo], [3.0.2])
33
44 dnl Detect the canonical target build environment
55 AC_CANONICAL_TARGET
4646 dnl
4747 AC_CHECK_SIZEOF(char)
4848 AC_CHECK_SIZEOF(short)
49 AC_CHECK_SIZEOF(long)
50 AC_CHECK_SIZEOF(int)
49 AC_CHECK_SIZEOF(long)
50 AC_CHECK_SIZEOF(int)
5151 AC_CHECK_SIZEOF(void *)
5252
5353 AC_TYPE_INT16_T
303303
304304 dnl ----------------------
305305 dnl Check if we need to
306 dnl support the old
306 dnl support the old
307307 dnl iconv interface
308308 dnl ----------------------
309309 if test "x$iconv_ok" = "xyes"; then
369369 else
370370 AC_MSG_RESULT(no. Now we will try some libraries.)
371371
372 AC_SEARCH_LIBS(pthread_create, pthread,
373 LIBPTHREADS_LIBS="-lpthread",
374 AC_SEARCH_LIBS(pthread_create, pthreads,
372 AC_SEARCH_LIBS(pthread_create, pthread,
373 LIBPTHREADS_LIBS="-lpthread",
374 AC_SEARCH_LIBS(pthread_create, pthreads,
375375 LIBPTHREADS_LIBS="-lpthreads",
376376 AC_SEARCH_LIBS(pthread_create, c_r,
377377 LIBPTHREADS_LIBS="-lc_r", thread_ok=no)))
164164 #
165165 # See http://zytrax.com/tech/web/browser_ids.htm for a compilation of strings.
166166 #
167 # http_user_agent="Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6"
168 # http_user_agent="Wget/1.11.4"
169 #The default is Dillo/(current version number)
167 # http_user_agent="Mozilla/5.0 (Windows NT 5.1; rv:7.0.1) Gecko/20100101 Firefox/7.0.1"
168 # http_user_agent="Wget/1.12 (linux-gnu)"
169 #The default is "Dillo/"+current_version_number
170170
171171 #-------------------------------------------------------------------------
172172 # COLORS SECTION
239239
240240 # A mouse's middle click over a tab closes the Tab.
241241 # With mousewheel mouses, right click feels way better (set to YES).
242 #right_click_closes_tab=NO
242 #right_click_closes_tab=NO
243243
244244 # Mouse middle click by default drives drag-scrolling.
245245 # To paste an URL into the window instead of scrolling, set it to NO.
133133 }
134134
135135 /*
136 * Clear the contents of the string
137 */
138 void dStrshred(char *s)
139 {
140 if (s)
141 memset(s, 0, strlen(s));
142 }
143
144 /*
136145 * Return a new string of length 'len' filled with 'c' characters
137146 */
138147 char *dStrnfill(size_t len, char c)
163172 }
164173
165174 /*
175 * ASCII functions to avoid the case difficulties introduced by I/i in
176 * Turkic locales.
177 */
178
179 /*
166180 * Case insensitive strstr
167181 */
168 char *dStristr(const char *haystack, const char *needle)
182 char *dStriAsciiStr(const char *haystack, const char *needle)
169183 {
170184 int i, j;
171185 char *ret = NULL;
172186
173187 if (haystack && needle) {
174188 for (i = 0, j = 0; haystack[i] && needle[j]; ++i)
175 if (tolower(haystack[i]) == tolower(needle[j])) {
189 if (D_ASCII_TOLOWER(haystack[i]) == D_ASCII_TOLOWER(needle[j])) {
176190 ++j;
177191 } else if (j) {
178192 i -= j;
184198 return ret;
185199 }
186200
201 int dStrAsciiCasecmp(const char *s1, const char *s2)
202 {
203 int ret = 0;
204
205 while ((*s1 || *s2) &&
206 !(ret = D_ASCII_TOLOWER(*s1) - D_ASCII_TOLOWER(*s2))) {
207 s1++;
208 s2++;
209 }
210 return ret;
211 }
212
213 int dStrnAsciiCasecmp(const char *s1, const char *s2, size_t n)
214 {
215 int ret = 0;
216
217 while (n-- && (*s1 || *s2) &&
218 !(ret = D_ASCII_TOLOWER(*s1) - D_ASCII_TOLOWER(*s2))) {
219 s1++;
220 s2++;
221 }
222 return ret;
223 }
187224
188225 /*
189226 *- dStr ----------------------------------------------------------------------
332369 ds->str[len] = 0;
333370 ds->len = len;
334371 }
372 }
373
374 /*
375 * Clear a Dstr.
376 */
377 void dStr_shred (Dstr *ds)
378 {
379 if (ds && ds->sz > 0)
380 memset(ds->str, '\0', ds->sz);
335381 }
336382
337383 /*
44 #include <stddef.h> /* for size_t */
55 #include <stdarg.h> /* for va_list */
66 #include <string.h> /* for strerror */
7 #include <strings.h> /* for strcasecmp, strncasecmp (POSIX 2001) */
87
98 #include "d_size.h"
109
3332 #define dIsspace(c) isspace((uchar_t)(c))
3433 #define dIsalnum(c) isalnum((uchar_t)(c))
3534
35 #define D_ASCII_TOUPPER(c) (((c) >= 'a' && (c) <= 'z') ? (c) - 0x20 : (c))
36 #define D_ASCII_TOLOWER(c) (((c) >= 'A' && (c) <= 'Z') ? (c) + 0x20 : (c))
3637 /*
3738 *-- Casts -------------------------------------------------------------------
3839 */
8586 char *dStrstrip(char *s);
8687 char *dStrnfill(size_t len, char c);
8788 char *dStrsep(char **orig, const char *delim);
88 char *dStristr(const char *haystack, const char *needle);
89 void dStrshred(char *s);
90 char *dStriAsciiStr(const char *haystack, const char *needle);
91 int dStrAsciiCasecmp(const char *s1, const char *s2);
92 int dStrnAsciiCasecmp(const char *s1, const char *s2, size_t n);
8993
90 /* these are in POSIX 2001. Could be implemented if a port requires it */
91 #define dStrcasecmp strcasecmp
92 #define dStrncasecmp strncasecmp
9394 #define dStrerror strerror
9495
9596 /*
113114 void dStr_insert (Dstr *ds, int pos_0, const char *s);
114115 void dStr_insert_l (Dstr *ds, int pos_0, const char *s, int l);
115116 void dStr_truncate (Dstr *ds, int len);
117 void dStr_shred (Dstr *ds);
116118 void dStr_erase (Dstr *ds, int pos_0, int len);
117119 void dStr_vsprintfa (Dstr *ds, const char *format, va_list argp);
118120 void dStr_vsprintf (Dstr *ds, const char *format, va_list argp);
0 .TH dillo 1 "August 5, 2010" "version 2.2" "USER COMMANDS"
0 .TH dillo 1 "October 13, 2011" "" "USER COMMANDS"
11 .SH NAME
22 dillo \- web browser
33 .SH SYNOPSIS
1616 downloader.
1717 .PP
1818 Dillo displays HTML, text, PNG, JPEG, and GIF files.
19 It handles cookies, basic authentication, proxying, and some CSS.
19 It handles cookies, HTTP authentication (basic and digest), proxying (basic),
20 and some CSS.
2021 .PP
2122 Framesets are displayed as links to frames, and there is currently
2223 no support for javascript or video.
22
33 <head>
44 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
5 <title> Dillo Web Browser ::
5 <title> Dillo Web Browser ::
66
77 Help for New Users
88
5353 </ul>
5454 </td></tr>
5555 </table>
56
56
5757 <table WIDTH="100%" BORDER=1 CELLSPACING=0 CELLPADDING=3>
5858 <tr ALIGN=LEFT VALIGN=TOP><td bgcolor="wheat">
5959 <h4><font color="green">Usage:</font></h4>
7676 <li> <b>Configuration:</b> If you want to change Dillo's
7777 appearance or behaviour, look at the options in your
7878 <b><font color="#5040a0">dillorc</font></b>
79 file (if you don't have a copy in your ~/.dillo/ directory, get it
80 <a href='http://www.dillo.org/dillorc'>here</a>).
79 file (if you don't have a copy in your ~/.dillo/ directory, get it
80 <a href='http://www.dillo.org/dillorc'>here</a>).
8181
8282 <li> Clicking the "Reload" button always requests an end-to-end reload
8383 of the page currently viewed, but it will *not* reload embedded
194194 That is, if you just compile and use dillo, it will reject
195195 every single cookie sent to it!
196196 <p>
197 If you want to enable cookies in dillo, please read
197 If you want to enable cookies in dillo, please read
198198 <a href="Cookies.txt">Cookies.txt</a>. It's very easy --
199199 just a matter of setting up a <code>cookiesrc</code> file).
200200 </td></tr>
251251 (<a href='http://www.dillo.org/dpi1.html'>dpi</a>) framework.
252252 This should be transparent to the end user. Please note that:
253253 <ul>
254 <li>It is a good idea to keep a backup of your
254 <li>It is a good idea to keep a backup of your
255255 <code>~/.dillo/bm.txt</code>
256256 <li>The server will stay alive after closing dillo.
257257 <li>You can stop the server by sending it a KILL signal. Dillo
307307 <tr><td>Back or "<b>,</b>" <td>< <td>previous page
308308 <tr><td>Shift-Back or "<b>.</b>" <td>> <td>next page
309309 <tr><td>Alt-F <td>File <td>file menu
310 <tr><td>Ctrl-TabKey <td>TabKey <td>Next tab
311 <tr><td>Ctrl-Shift-TabKey <td>TabKey <td>Previous tab
310 <tr><td>Ctrl-TabKey or
311 Ctrl-PageDown <td>TabKey <td>Next tab
312 <tr><td>Ctrl-Shift-TabKey or
313 Ctrl-PageUp <td>TabKey <td>Previous tab
312314 <tr><td>Esc <td>escape <td>close dialog,
313315 close findbar,<br>
314316 Hide/show control panels
441441 if (*e == '+') {
442442 *p = ' ';
443443 } else if (*e == '%') {
444 if (dStrncasecmp(e, "%0D%0A", 6) == 0) {
444 if (dStrnAsciiCasecmp(e, "%0D%0A", 6) == 0) {
445445 *p = '\n';
446446 e += 5;
447447 } else {
16251625 dFree(cmd);
16261626 url = a_Dpip_get_attr_l(Buf, BufSize, "url");
16271627
1628 if (strcmp(url, "dpi:/bm/modify") == 0) {
1629 st = Bmsrv_send_modify_answer(sh, url);
1630 dFree(url);
1631 return st;
1632
1633 } else if (strncmp(url, "dpi:/bm/modify?", 15) == 0) {
1634 /* process request */
1635 st = Bmsrv_process_modify_request(sh, url);
1636 dFree(url);
1637 return st;
1628 if (dStrnAsciiCasecmp(url, "dpi:", 4) == 0) {
1629 if (strcmp(url+4, "/bm/modify") == 0) {
1630 st = Bmsrv_send_modify_answer(sh, url);
1631 dFree(url);
1632 return st;
1633 } else if (strncmp(url+4, "/bm/modify?", 11) == 0) {
1634 /* process request */
1635 st = Bmsrv_process_modify_request(sh, url);
1636 dFree(url);
1637 return st;
1638 }
16381639 }
16391640
16401641
157157 {
158158 const DomainNode *n1 = v1, *n2 = v2;
159159
160 return dStrcasecmp(n1->domain, n2->domain);
160 return dStrAsciiCasecmp(n1->domain, n2->domain);
161161 }
162162
163163 /*
168168 const DomainNode *node = v1;
169169 const char *domain = v2;
170170
171 return dStrcasecmp(node->domain, domain);
171 return dStrAsciiCasecmp(node->domain, domain);
172172 }
173173
174174 /*
467467 int i;
468468
469469 for (i = 0; i < 12; i++) {
470 if (!dStrncasecmp(months[i], month_name, 3))
470 if (!dStrnAsciiCasecmp(months[i], month_name, 3))
471471 return i;
472472 }
473473 return -1;
820820 cookie->expires_at = mktime(tm);
821821 if (cookie->expires_at == (time_t) -1)
822822 cookie->expires_at = cookies_future_time;
823 } else if (dStrcasecmp(attr, "Path") == 0) {
823 } else if (dStrAsciiCasecmp(attr, "Path") == 0) {
824824 value = Cookies_parse_value(&str);
825825 dFree(cookie->path);
826826 cookie->path = value;
827 } else if (dStrcasecmp(attr, "Domain") == 0) {
827 } else if (dStrAsciiCasecmp(attr, "Domain") == 0) {
828828 value = Cookies_parse_value(&str);
829829 dFree(cookie->domain);
830830 cookie->domain = value;
831 } else if (dStrcasecmp(attr, "Max-Age") == 0) {
831 } else if (dStrAsciiCasecmp(attr, "Max-Age") == 0) {
832832 value = Cookies_parse_value(&str);
833833 if (isdigit(*value) || *value == '-') {
834834 time_t now = time(NULL);
844844 expires = max_age = TRUE;
845845 }
846846 dFree(value);
847 } else if (dStrcasecmp(attr, "Expires") == 0) {
847 } else if (dStrAsciiCasecmp(attr, "Expires") == 0) {
848848 if (!max_age) {
849849 value = Cookies_parse_value(&str);
850850 Cookies_unquote_string(value);
869869 } else {
870870 Cookies_eat_value(&str);
871871 }
872 } else if (dStrcasecmp(attr, "Secure") == 0) {
872 } else if (dStrAsciiCasecmp(attr, "Secure") == 0) {
873873 cookie->secure = TRUE;
874874 Cookies_eat_value(&str);
875 } else if (dStrcasecmp(attr, "HttpOnly") == 0) {
875 } else if (dStrAsciiCasecmp(attr, "HttpOnly") == 0) {
876876 Cookies_eat_value(&str);
877877 } else {
878878 MSG("Cookie contains unknown attribute: '%s'\n", attr);
919919 _MSG("an IPv4 address\n");
920920 return TRUE;
921921 }
922 if (*domain == '[' &&
923 (len == strspn(domain, "0123456789abcdefABCDEF:.[]"))) {
922 if (strchr(domain, ':') &&
923 (len == strspn(domain, "0123456789abcdefABCDEF:."))) {
924924 /* The precise format is shown in section 3.2.2 of rfc 3986 */
925 _MSG("an IPv6 address\n");
925 MSG("an IPv6 address\n");
926926 return TRUE;
927927 }
928928 return FALSE;
991991 * don't, so: No.
992992 */
993993
994 if (!dStrcasecmp(A, B))
994 if (!dStrAsciiCasecmp(A, B))
995995 return TRUE;
996996
997997 if (Cookies_domain_is_ip(B))
10011001
10021002 if (diff > 0) {
10031003 /* B is the tail of A, and the match is preceded by a '.' */
1004 return (dStrcasecmp(A + diff, B) == 0 && A[diff - 1] == '.');
1004 return (dStrAsciiCasecmp(A + diff, B) == 0 && A[diff - 1] == '.');
10051005 } else {
10061006 return FALSE;
10071007 }
10491049
10501050 for (i = 0; i < tld_num; i++) {
10511051 if (strlen(tlds[i]) == (uint_t) tld_len &&
1052 !dStrncasecmp(tlds[i], host + start, tld_len)) {
1052 !dStrnAsciiCasecmp(tlds[i], host + start, tld_len)) {
10531053 _MSG("TLD code matched %s\n", tlds[i]);
10541054 ret++;
10551055 break;
12201220 matching_cookies = dList_new(8);
12211221
12221222 /* Check if the protocol is secure or not */
1223 is_ssl = (!dStrcasecmp(url_scheme, "https"));
1223 is_ssl = (!dStrAsciiCasecmp(url_scheme, "https"));
12241224
12251225 is_ip_addr = Cookies_domain_is_ip(url_host);
12261226
13491349 rule[j++] = line[i++];
13501350 rule[j] = '\0';
13511351
1352 if (dStrcasecmp(rule, "ACCEPT") == 0)
1352 if (dStrAsciiCasecmp(rule, "ACCEPT") == 0)
13531353 cc.action = COOKIE_ACCEPT;
1354 else if (dStrcasecmp(rule, "ACCEPT_SESSION") == 0)
1354 else if (dStrAsciiCasecmp(rule, "ACCEPT_SESSION") == 0)
13551355 cc.action = COOKIE_ACCEPT_SESSION;
1356 else if (dStrcasecmp(rule, "DENY") == 0)
1356 else if (dStrAsciiCasecmp(rule, "DENY") == 0)
13571357 cc.action = COOKIE_DENY;
13581358 else {
13591359 MSG("Cookies: rule '%s' for domain '%s' is not recognised.\n",
13621362 }
13631363
13641364 cc.domain = dStrdup(domain);
1365 if (dStrcasecmp(cc.domain, "DEFAULT") == 0) {
1365 if (dStrAsciiCasecmp(cc.domain, "DEFAULT") == 0) {
13661366 /* Set the default action */
13671367 default_action = cc.action;
13681368 dFree(cc.domain);
14031403 if (ccontrol[i].domain[0] == '.') {
14041404 diff = strlen(domain) - strlen(ccontrol[i].domain);
14051405 if (diff >= 0) {
1406 if (dStrcasecmp(domain + diff, ccontrol[i].domain) != 0)
1406 if (dStrAsciiCasecmp(domain + diff, ccontrol[i].domain) != 0)
14071407 continue;
14081408 } else {
14091409 continue;
14101410 }
14111411 } else {
1412 if (dStrcasecmp(domain, ccontrol[i].domain) != 0)
1412 if (dStrAsciiCasecmp(domain, ccontrol[i].domain) != 0)
14131413 continue;
14141414 }
14151415
4343 MSG("len=%d{%s}\n", strlen((char*)str), str);
4444
4545 for (p = s; (*p = *s); ++s) {
46 if (isalnum(*p) || strchr("+/=", *p))
46 if (isascii(*p) && (isalnum(*p) || strchr("+/=", *p)))
4747 ++p;
4848 }
4949
225225 char *mime_type = NULL, *p;
226226 size_t len = 0;
227227
228 if (dStrncasecmp(url, "data:", 5) == 0) {
228 if (dStrnAsciiCasecmp(url, "data:", 5) == 0) {
229229 if ((p = strchr(url, ',')) && p - url < 256) {
230230 url += 5;
231231 len = p - url;
232232 strncpy(buf, url, len);
233233 buf[len] = 0;
234234 /* strip ";base64" */
235 if (len >= 7 && dStrcasecmp(buf + len - 7, ";base64") == 0) {
235 if (len >= 7 && dStrAsciiCasecmp(buf + len - 7, ";base64") == 0) {
236236 len -= 7;
237237 buf[len] = 0;
238238 }
241241 /* that's it, now handle omitted types */
242242 if (len == 0) {
243243 mime_type = dStrdup("text/plain;charset=US-ASCII");
244 } else if (!dStrncasecmp(buf, "charset", 7)) {
244 } else if (!dStrnAsciiCasecmp(buf, "charset", 7)) {
245245 mime_type = dStrconcat("text/plain", buf, NULL);
246246 } else {
247247 mime_type = dStrdup(buf);
261261 unsigned char *data = NULL;
262262
263263 if ((p = strchr(url, ',')) && p - url >= 12 && /* "data:;base64" */
264 dStrncasecmp(p - 7, ";base64", 7) == 0) {
264 dStrnAsciiCasecmp(p - 7, ";base64", 7) == 0) {
265265 is_base64 = 1;
266266 }
267267
326326 /* escape "'" character for the shell. Is it necessary? */
327327 esc_url = Escape_uri_str(url, "'");
328328 /* avoid malicious SMTP relaying with FTP urls */
329 if (dStrncasecmp(esc_url, "ftp:/", 5) == 0)
329 if (dStrnAsciiCasecmp(esc_url, "ftp:/", 5) == 0)
330330 Filter_smtp_hack(esc_url);
331331 dl_argv = new char*[8];
332332 int i = 0;
353353 gw = 400, gh = 70;
354354 group = new Fl_Group(0,0,gw,gh);
355355 group->begin();
356 prTitle = new Fl_Box(24, 7, 290, 23);
357 prTitle->box(FL_RSHADOW_BOX);
358 prTitle->color(FL_WHITE);
359 prTitle->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP);
360 prTitle->copy_label(shortname);
361 // Attach this 'log_text' to the tooltip
362 log_text_add("Target File: ", 13);
363 log_text_add(fullname, strlen(fullname));
364 log_text_add("\n\n", 2);
365
366 prBar = new ProgressBar(24, 40, 92, 20);
367 prBar->box(FL_THIN_UP_BOX);
368 prBar->tooltip("Progress Status");
369
370 int ix = 122, iy = 37, iw = 50, ih = 14;
371 Fl_Widget *o = new Fl_Box(ix,iy,iw,ih, "Got");
372 o->box(FL_RFLAT_BOX);
373 o->color(FL_DARK2);
374 o->labelsize(12);
375 o->tooltip("Downloaded Size");
376 prGot = new Fl_Box(ix,iy+14,iw,ih, "0KB");
377 prGot->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
378 prGot->labelcolor(FL_BLUE);
379 prGot->labelsize(12);
380 prGot->box(FL_NO_BOX);
381
382 ix += iw;
383 o = new Fl_Box(ix,iy,iw,ih, "Size");
384 o->box(FL_RFLAT_BOX);
385 o->color(FL_DARK2);
386 o->labelsize(12);
387 o->tooltip("Total Size");
388 prSize = new Fl_Box(ix,iy+14,iw,ih, "??");
389 prSize->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
390 prSize->labelsize(12);
391 prSize->box(FL_NO_BOX);
392
393 ix += iw;
394 o = new Fl_Box(ix,iy,iw,ih, "Rate");
395 o->box(FL_RFLAT_BOX);
396 o->color(FL_DARK2);
397 o->labelsize(12);
398 o->tooltip("Current transfer Rate (KBytes/sec)");
399 prRate = new Fl_Box(ix,iy+14,iw,ih, "??");
400 prRate->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
401 prRate->labelsize(12);
402 prRate->box(FL_NO_BOX);
403
404 ix += iw;
405 o = new Fl_Box(ix,iy,iw,ih, "~Rate");
406 o->box(FL_RFLAT_BOX);
407 o->color(FL_DARK2);
408 o->labelsize(12);
409 o->tooltip("Average transfer Rate (KBytes/sec)");
410 pr_Rate = new Fl_Box(ix,iy+14,iw,ih, "??");
411 pr_Rate->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
412 pr_Rate->labelsize(12);
413 pr_Rate->box(FL_NO_BOX);
414
415 ix += iw;
416 prETAt = o = new Fl_Box(ix,iy,iw,ih, "ETA");
417 o->box(FL_RFLAT_BOX);
418 o->color(FL_DARK2);
419 o->labelsize(12);
420 o->tooltip("Estimated Time of Arrival");
421 prETA = new Fl_Box(ix,iy+14,iw,ih, "??");
422 prETA->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
423 prETA->labelsize(12);
424 prETA->box(FL_NO_BOX);
425
426 prButton = new Fl_Button(326, 9, 44, 19, "Stop");
427 prButton->tooltip("Stop this transfer");
428 prButton->box(FL_UP_BOX);
429 prButton->clear_visible_focus();
430 prButton->callback(prButton_scb, this);
356 prTitle = new Fl_Box(24, 7, 290, 23);
357 prTitle->box(FL_RSHADOW_BOX);
358 prTitle->color(FL_WHITE);
359 prTitle->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP);
360 prTitle->copy_label(shortname);
361 // Attach this 'log_text' to the tooltip
362 log_text_add("Target File: ", 13);
363 log_text_add(fullname, strlen(fullname));
364 log_text_add("\n\n", 2);
365
366 prBar = new ProgressBar(24, 40, 92, 20);
367 prBar->box(FL_THIN_UP_BOX);
368 prBar->tooltip("Progress Status");
369
370 int ix = 122, iy = 37, iw = 50, ih = 14;
371 Fl_Widget *o = new Fl_Box(ix,iy,iw,ih, "Got");
372 o->box(FL_RFLAT_BOX);
373 o->color(FL_DARK2);
374 o->labelsize(12);
375 o->tooltip("Downloaded Size");
376 prGot = new Fl_Box(ix,iy+14,iw,ih, "0KB");
377 prGot->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
378 prGot->labelcolor(FL_BLUE);
379 prGot->labelsize(12);
380 prGot->box(FL_NO_BOX);
381
382 ix += iw;
383 o = new Fl_Box(ix,iy,iw,ih, "Size");
384 o->box(FL_RFLAT_BOX);
385 o->color(FL_DARK2);
386 o->labelsize(12);
387 o->tooltip("Total Size");
388 prSize = new Fl_Box(ix,iy+14,iw,ih, "??");
389 prSize->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
390 prSize->labelsize(12);
391 prSize->box(FL_NO_BOX);
392
393 ix += iw;
394 o = new Fl_Box(ix,iy,iw,ih, "Rate");
395 o->box(FL_RFLAT_BOX);
396 o->color(FL_DARK2);
397 o->labelsize(12);
398 o->tooltip("Current transfer Rate (KBytes/sec)");
399 prRate = new Fl_Box(ix,iy+14,iw,ih, "??");
400 prRate->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
401 prRate->labelsize(12);
402 prRate->box(FL_NO_BOX);
403
404 ix += iw;
405 o = new Fl_Box(ix,iy,iw,ih, "~Rate");
406 o->box(FL_RFLAT_BOX);
407 o->color(FL_DARK2);
408 o->labelsize(12);
409 o->tooltip("Average transfer Rate (KBytes/sec)");
410 pr_Rate = new Fl_Box(ix,iy+14,iw,ih, "??");
411 pr_Rate->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
412 pr_Rate->labelsize(12);
413 pr_Rate->box(FL_NO_BOX);
414
415 ix += iw;
416 prETAt = o = new Fl_Box(ix,iy,iw,ih, "ETA");
417 o->box(FL_RFLAT_BOX);
418 o->color(FL_DARK2);
419 o->labelsize(12);
420 o->tooltip("Estimated Time of Arrival");
421 prETA = new Fl_Box(ix,iy+14,iw,ih, "??");
422 prETA->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
423 prETA->labelsize(12);
424 prETA->box(FL_NO_BOX);
425
426 prButton = new Fl_Button(326, 9, 44, 19, "Stop");
427 prButton->tooltip("Stop this transfer");
428 prButton->box(FL_UP_BOX);
429 prButton->clear_visible_focus();
430 prButton->callback(prButton_scb, this);
431431
432432 group->box(FL_ROUNDED_BOX);
433433 group->end();
10861086 }
10871087
10881088 /*
1089 * A Scroll class that resizes its resizable widget to its width.
1090 * see http://seriss.com/people/erco/fltk/#ScrollableWidgetBrowser
1091 */
1092 class DlScroll : public Fl_Scroll
1093 {
1094 public:
1095 void resize(int x_, int y_, int w_, int h_)
1096 {
1097 Fl_Widget *resizable_ = resizable();
1098 if (resizable_)
1099 resizable_->resize(resizable_->x(),
1100 resizable_->y(),
1101 w() - scrollbar_size(),
1102 resizable_->h());
1103 Fl_Scroll::resize(x_, y_, w_, h_);
1104 }
1105 DlScroll(int x, int y, int w, int h, const char *l = 0)
1106 : Fl_Scroll(x, y, w, h, l)
1107 {
1108 }
1109 };
1110
1111 /*
10891112 * Create the main window and an empty list of requests.
10901113 */
10911114 DLWin::DLWin(int ww, int wh) {
10961119 // Create the empty main window
10971120 mWin = new Fl_Window(ww, wh, "Downloads:");
10981121 mWin->begin();
1099 mScroll = new Fl_Scroll(0,0,ww,wh);
1100 mScroll->begin();
1101 mPG = new Fl_Pack(0,0,ww-18,wh);
1102 mPG->end();
1103 mScroll->end();
1104 mScroll->type(Fl_Scroll::VERTICAL);
1122 mScroll = new DlScroll(0,0,ww,wh);
1123 mScroll->begin();
1124 mPG = new Fl_Pack(0,0,ww-18,wh);
1125 mPG->end();
1126 mScroll->end();
1127 mScroll->type(Fl_Scroll::VERTICAL);
1128 mScroll->resizable(mPG);
11051129 mWin->end();
11061130 mWin->resizable(mScroll);
11071131 mWin->callback(dlwin_esc_cb, NULL);
6767 if (strchr(s, '%')) {
6868 for (p = buf; (*p = *s); ++s, ++p) {
6969 if (*p == '%' && isxdigit(s[1]) && isxdigit(s[2])) {
70 *p = (isdigit(s[1]) ? (s[1] - '0') : toupper(s[1]) - 'A' + 10)*16;
71 *p += isdigit(s[2]) ? (s[2] - '0') : toupper(s[2]) - 'A' + 10;
70 *p = (isdigit(s[1]) ? (s[1] - '0')
71 : D_ASCII_TOUPPER(s[1]) - 'A' + 10) * 16;
72 *p += isdigit(s[2]) ? (s[2] - '0')
73 : D_ASCII_TOUPPER(s[2]) - 'A' + 10;
7274 s += 2;
7375 }
7476 }
120122 for (i = 0, j = 0; str[i]; ++i) {
121123 if (str[i] == '&') {
122124 for (k = 0; k < 5; ++k) {
123 if (!dStrncasecmp(str + i, unsafe_rep[k], unsafe_rep_len[k])) {
125 if (!dStrnAsciiCasecmp(str + i, unsafe_rep[k], unsafe_rep_len[k])) {
124126 i += unsafe_rep_len[k] - 1;
125127 break;
126128 }
153155 memmove(url + i, url + i + 1, strlen(url + i));
154156 --i;
155157 } else if (c == '%' && url[i+1] == '0' &&
156 (tolower(url[i+2]) == 'a' || tolower(url[i+2]) == 'd')) {
158 (D_ASCII_TOLOWER(url[i+2]) == 'a' ||
159 D_ASCII_TOLOWER(url[i+2]) == 'd')) {
157160 memmove(url + i, url + i + 3, strlen(url + i + 2));
158161 --i;
159162 }
1414 * With new HTML layout.
1515 */
1616
17 #include <ctype.h> /* for tolower */
17 #include <ctype.h> /* for isspace */
1818 #include <errno.h> /* for errno */
1919 #include <stdio.h>
2020 #include <stdlib.h>
141141
142142 /* HTML try */
143143 for (i = 0; i < Size && dIsspace(p[i]); ++i);
144 if ((Size - i >= 5 && !dStrncasecmp(p+i, "<html", 5)) ||
145 (Size - i >= 5 && !dStrncasecmp(p+i, "<head", 5)) ||
146 (Size - i >= 6 && !dStrncasecmp(p+i, "<title", 6)) ||
147 (Size - i >= 14 && !dStrncasecmp(p+i, "<!doctype html", 14)) ||
144 if ((Size - i >= 5 && !dStrnAsciiCasecmp(p+i, "<html", 5)) ||
145 (Size - i >= 5 && !dStrnAsciiCasecmp(p+i, "<head", 5)) ||
146 (Size - i >= 6 && !dStrnAsciiCasecmp(p+i, "<title", 6)) ||
147 (Size - i >= 14 && !dStrnAsciiCasecmp(p+i, "<!doctype html", 14)) ||
148148 /* this line is workaround for FTP through the Squid proxy */
149 (Size - i >= 17 && !dStrncasecmp(p+i, "<!-- HTML listing", 17))) {
149 (Size - i >= 17 && !dStrnAsciiCasecmp(p+i, "<!-- HTML listing", 17))) {
150150
151151 Type = 1;
152152
153153 /* Images */
154 } else if (Size >= 4 && !dStrncasecmp(p, "GIF8", 4)) {
154 } else if (Size >= 4 && !strncmp(p, "GIF8", 4)) {
155155 Type = 3;
156 } else if (Size >= 4 && !dStrncasecmp(p, "\x89PNG", 4)) {
156 } else if (Size >= 4 && !strncmp(p, "\x89PNG", 4)) {
157157 Type = 4;
158 } else if (Size >= 2 && !dStrncasecmp(p, "\xff\xd8", 2)) {
158 } else if (Size >= 2 && !strncmp(p, "\xff\xd8", 2)) {
159159 /* JPEG has the first 2 bytes set to 0xffd8 in BigEndian - looking
160160 * at the character representation should be machine independent. */
161161 Type = 5;
501501
502502 e++;
503503
504 if (!dStrcasecmp(e, "gif")) {
504 if (!dStrAsciiCasecmp(e, "gif")) {
505505 return "image/gif";
506 } else if (!dStrcasecmp(e, "jpg") ||
507 !dStrcasecmp(e, "jpeg")) {
506 } else if (!dStrAsciiCasecmp(e, "jpg") ||
507 !dStrAsciiCasecmp(e, "jpeg")) {
508508 return "image/jpeg";
509 } else if (!dStrcasecmp(e, "png")) {
509 } else if (!dStrAsciiCasecmp(e, "png")) {
510510 return "image/png";
511 } else if (!dStrcasecmp(e, "html") ||
512 !dStrcasecmp(e, "htm") ||
513 !dStrcasecmp(e, "shtml")) {
511 } else if (!dStrAsciiCasecmp(e, "html") ||
512 !dStrAsciiCasecmp(e, "htm") ||
513 !dStrAsciiCasecmp(e, "shtml")) {
514514 return "text/html";
515 } else if (!dStrcasecmp(e, "txt")) {
515 } else if (!dStrAsciiCasecmp(e, "txt")) {
516516 return "text/plain";
517517 } else {
518518 return NULL;
711711
712712 /* Check for gzipped file */
713713 namelen = strlen(client->filename);
714 if (namelen > 3 && !dStrcasecmp(client->filename + namelen - 3, ".gz")) {
714 if (namelen > 3 &&
715 !dStrAsciiCasecmp(client->filename + namelen - 3, ".gz")) {
715716 gzipped = TRUE;
716717 namelen -= 3;
717718 }
798799 dReturn_val_if (orig == NULL, ret);
799800
800801 /* Make sure the string starts with "file:/" */
801 if (strncmp(str, "file:/", 5) != 0)
802 if (dStrnAsciiCasecmp(str, "file:/", 5) != 0)
802803 return ret;
803804 str += 5;
804805
805806 /* Skip "localhost" */
806 if (dStrncasecmp(str, "//localhost/", 12) == 0)
807 if (dStrnAsciiCasecmp(str, "//localhost/", 12) == 0)
807808 str += 11;
808809
809810 /* Skip packed slashes, and leave just one */
940941 DPIBYE = 1;
941942 MSG("(pid %d): Got DpiBye.\n", (int)getpid());
942943 client->flags |= FILE_DONE;
943 } else if (url && strcmp(url, "dpi:/file/toggle") == 0) {
944 } else if (url && dStrnAsciiCasecmp(url, "dpi:", 4) == 0 &&
945 strcmp(url+4, "/file/toggle") == 0) {
944946 File_toggle_html_style(client);
945947 } else if (path) {
946948 File_get(client, path, url);
9797
9898 /* HTML try */
9999 for (i = 0; i < Size && dIsspace(p[i]); ++i);
100 if ((Size - i >= 5 && !dStrncasecmp(p+i, "<html", 5)) ||
101 (Size - i >= 5 && !dStrncasecmp(p+i, "<head", 5)) ||
102 (Size - i >= 6 && !dStrncasecmp(p+i, "<title", 6)) ||
103 (Size - i >= 14 && !dStrncasecmp(p+i, "<!doctype html", 14)) ||
100 if ((Size - i >= 5 && !dStrnAsciiCasecmp(p+i, "<html", 5)) ||
101 (Size - i >= 5 && !dStrnAsciiCasecmp(p+i, "<head", 5)) ||
102 (Size - i >= 6 && !dStrnAsciiCasecmp(p+i, "<title", 6)) ||
103 (Size - i >= 14 && !dStrnAsciiCasecmp(p+i, "<!doctype html", 14)) ||
104104 /* this line is workaround for FTP through the Squid proxy */
105 (Size - i >= 17 && !dStrncasecmp(p+i, "<!-- HTML listing", 17))) {
105 (Size - i >= 17 && !dStrnAsciiCasecmp(p+i, "<!-- HTML listing", 17))) {
106106
107107 Type = 1;
108108 st = 0;
109109 /* Images */
110 } else if (Size >= 4 && !dStrncasecmp(p, "GIF8", 4)) {
110 } else if (Size >= 4 && !strncmp(p, "GIF8", 4)) {
111111 Type = 3;
112112 st = 0;
113 } else if (Size >= 4 && !dStrncasecmp(p, "\x89PNG", 4)) {
113 } else if (Size >= 4 && !strncmp(p, "\x89PNG", 4)) {
114114 Type = 4;
115115 st = 0;
116 } else if (Size >= 2 && !dStrncasecmp(p, "\xff\xd8", 2)) {
116 } else if (Size >= 2 && !strncmp(p, "\xff\xd8", 2)) {
117117 /* JPEG has the first 2 bytes set to 0xffd8 in BigEndian - looking
118118 * at the character representation should be machine independent. */
119119 Type = 5;
359359 char * url_look_up = NULL;
360360
361361 /*Determine how much of url we chop off as unneeded*/
362 if (dStrncasecmp(url, "https://", 8) == 0){
362 if (dStrnAsciiCasecmp(url, "https://", 8) == 0){
363363 url_offset = 8;
364 } else if (dStrncasecmp(url, "http://", 7) == 0) {
364 } else if (dStrnAsciiCasecmp(url, "http://", 7) == 0) {
365365 url_offset = 7;
366366 portnum = 80;
367367 }
100100 int bytes_read = 0, old_line = 0, line = 1;
101101 char *p, *q, *src_str, line_str[128];
102102
103 if (strncmp(url, "dpi:/vsource/:", 14) == 0)
103 if (dStrnAsciiCasecmp(url, "dpi:", 4) == 0 &&
104 strncmp(url+4, "/vsource/:", 10) == 0)
104105 url += 14;
105106
106107 /* Send HTTP header for plain text MIME type */
844844 if (A->name[A_len - 1] == '*')
845845 len = A_len - 1;
846846
847 return(dStrncasecmp(A->name, B, len));
847 return(dStrnAsciiCasecmp(A->name, B, len));
848848 }
849849
850850 /*!
0 // fltkcomplexbutton.cc contains code from FLTK 1.3's src/Fl_Button.cxx
1 // that is Copyright 1998-2010 by Bill Spitzak and others.
0 // fltkcomplexbutton.cc is derived from src/Fl_Button.cxx from FLTK's 1.3
1 // branch at http://fltk.org in early 2011.
2 // src/Fl_Button.cxx is Copyright 1998-2010 by Bill Spitzak and others.
23
34 /*
45 * This program is free software; you can redistribute it and/or modify
107108 return 1;
108109 } else return 0;
109110 case FL_KEYBOARD :
110 if (Fl::focus() == this && Fl::event_key() == ' ' &&
111 if (Fl::focus() == this &&
112 (Fl::event_key() == ' ' || Fl::event_key() == FL_Enter) &&
111113 !(Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT | FL_META))) {
112114 set_changed();
113115 Fl_Widget_Tracker wp(this);
00
1 // fltkcomplexbutton.hh contains code from FLTK 1.3's FL/Fl_Button.H
2 // that is Copyright 1998-2010 by Bill Spitzak and others.
1 // fltkcomplexbutton.hh is derived from FL/Fl_Button.H from FLTK's 1.3 branch
2 // at http://fltk.org in early 2011.
3 // FL/Fl_Button.H is Copyright 1998-2010 by Bill Spitzak and others.
34
45 /*
56 * This program is free software; you can redistribute it and/or modify
140140 static void strstrip(char *big, const char *little)
141141 {
142142 if (strlen(big) >= strlen(little) &&
143 strcasecmp(big + strlen(big) - strlen(little), little) == 0)
143 misc::AsciiStrcasecmp(big + strlen(big) - strlen(little), little) == 0)
144144 *(big + strlen(big) - strlen(little)) = '\0';
145145 }
146146
524524 if ((cu = fl_toupper(c)) == c) {
525525 /* already uppercase, just draw the character */
526526 fl_font(ff->font, ff->size);
527 width += font->letterSpacing;
528 width += (int)fl_width(text + curr, next - curr);
527 if (fl_nonspacing(cu) == 0) {
528 width += font->letterSpacing;
529 width += (int)fl_width(text + curr, next - curr);
530 }
529531 } else {
530532 /* make utf8 string for converted char */
531533 nb = fl_utf8encode(cu, chbuf);
532534 fl_font(ff->font, sc_fontsize);
533 width += font->letterSpacing;
534 width += (int)fl_width(chbuf, nb);
535 if (fl_nonspacing(cu) == 0) {
536 width += font->letterSpacing;
537 width += (int)fl_width(chbuf, nb);
538 }
535539 }
536540 }
537541 } else {
543547
544548 while (next < len) {
545549 next = nextGlyph(text, curr);
546 width += font->letterSpacing;
550 c = fl_utf8decode(text + curr, text + next, &nb);
551 if (fl_nonspacing(c) == 0)
552 width += font->letterSpacing;
547553 curr = next;
548554 }
549555 }
550556 }
551557
552558 return width;
559 }
560
561 char *FltkPlatform::textToUpper (const char *text, int len)
562 {
563 char *newstr = NULL;
564
565 if (len > 0) {
566 int newlen;
567
568 newstr = (char*) malloc(3 * len + 1);
569 newlen = fl_utf_toupper((const unsigned char*)text, len, newstr);
570 assert(newlen <= 3 * len);
571 newstr[newlen] = '\0';
572 }
573 return newstr;
574 }
575
576 char *FltkPlatform::textToLower (const char *text, int len)
577 {
578 char *newstr = NULL;
579
580 if (len > 0) {
581 int newlen;
582
583 newstr = (char*) malloc(3 * len + 1);
584 newlen = fl_utf_tolower((const unsigned char*)text, len, newstr);
585 assert(newlen <= 3 * len);
586 newstr[newlen] = '\0';
587 }
588 return newstr;
553589 }
554590
555591 int FltkPlatform::nextGlyph (const char *text, int idx)
152152 void detachView (core::View *view);
153153
154154 int textWidth (core::style::Font *font, const char *text, int len);
155 char *textToUpper (const char *text, int len);
156 char *textToLower (const char *text, int len);
155157 int nextGlyph (const char *text, int idx);
156158 int prevGlyph (const char *text, int idx);
157159 float dpiX ();
265265
266266 // ----------------------------------------------------------------------
267267
268 class EnterButton : public Fl_Button {
269 public:
270 EnterButton (int x,int y,int w,int h, const char* label = 0) :
271 Fl_Button (x,y,w,h,label) {};
272 int handle(int e);
273 };
274
275 int EnterButton::handle(int e)
276 {
277 if (e == FL_KEYBOARD && Fl::focus() == this && Fl::event_key() == FL_Enter){
278 set_changed();
279 simulate_key_action();
280 do_callback();
281 return 1;
282 }
283 return Fl_Button::handle(e);
284 }
285
268286 FltkLabelButtonResource::FltkLabelButtonResource (FltkPlatform *platform,
269287 const char *label):
270288 FltkSpecificResource <dw::core::ui::LabelButtonResource> (platform)
282300 *allocation)
283301 {
284302 Fl_Button *button =
285 new Fl_Button (allocation->x, allocation->y, allocation->width,
286 allocation->ascent + allocation->descent, label);
303 new EnterButton (allocation->x, allocation->y, allocation->width,
304 allocation->ascent + allocation->descent, label);
287305 button->callback (widgetCallback, this);
288306 button->when (FL_WHEN_RELEASE);
289307 return button;
547547 viewY = translateCanvasYToViewY (Y);
548548 int curr = 0, next = 0, nb;
549549 char chbuf[4];
550 int c, cu;
550 int c, cu, width;
551551
552552 if (font->fontVariant == core::style::FONT_VARIANT_SMALL_CAPS) {
553553 int sc_fontsize = lout::misc::roundInt(ff->size * 0.78);
557557 if ((cu = fl_toupper(c)) == c) {
558558 /* already uppercase, just draw the character */
559559 fl_font(ff->font, ff->size);
560 width = (int)fl_width(text + curr, next - curr);
561 if (curr && width)
562 viewX += font->letterSpacing;
560563 fl_draw(text + curr, next - curr, viewX, viewY);
561 viewX += font->letterSpacing;
562 viewX += (int)fl_width(text + curr, next - curr);
564 viewX += width;
563565 } else {
564566 /* make utf8 string for converted char */
565567 nb = fl_utf8encode(cu, chbuf);
566568 fl_font(ff->font, sc_fontsize);
569 width = (int)fl_width(chbuf, nb);
570 if (curr && width)
571 viewX += font->letterSpacing;
567572 fl_draw(chbuf, nb, viewX, viewY);
568 viewX += font->letterSpacing;
569 viewX += (int)fl_width(chbuf, nb);
573 viewX += width;
570574 }
571575 }
572576 } else {
573577 while (next < len) {
574578 next = theLayout->nextGlyph(text, curr);
579 width = (int)fl_width(text + curr, next - curr);
580 if (curr && width)
581 viewX += font->letterSpacing;
575582 fl_draw(text + curr, next - curr, viewX, viewY);
576 viewX += font->letterSpacing +
577 (int)fl_width(text + curr,next - curr);
583 viewX += width;
578584 curr = next;
579585 }
580586 }
296296 return platform->textWidth (font, text, len);
297297 }
298298
299 inline char *textToUpper (const char *text, int len)
300 {
301 return platform->textToUpper (text, len);
302 }
303
304 inline char *textToLower (const char *text, int len)
305 {
306 return platform->textToLower (text, len);
307 }
308
299309 inline int nextGlyph (const char *text, int idx)
300310 {
301311 return platform->nextGlyph (text, idx);
5555 * \brief Return the width of a text, with a given length and font.
5656 */
5757 virtual int textWidth (style::Font *font, const char *text, int len) = 0;
58
59 /**
60 * \brief Return the string resulting from transforming text to uppercase.
61 */
62 virtual char *textToUpper (const char *text, int len) = 0;
63
64 /**
65 * \brief Return the string resulting from transforming text to lowercase.
66 */
67 virtual char *textToLower (const char *text, int len) = 0;
5868
5969 /**
6070 * \brief Return the index of the next glyph in string text.
4141 textDecoration = TEXT_DECORATION_NONE;
4242 textAlign = TEXT_ALIGN_LEFT;
4343 textAlignChar = '.';
44 textTransform = TEXT_TRANSFORM_NONE;
4445 listStylePosition = LIST_STYLE_POSITION_OUTSIDE;
4546 listStyleType = LIST_STYLE_TYPE_DISC;
4647 valign = VALIGN_BASELINE;
116117 textAlign == otherAttrs->textAlign &&
117118 valign == otherAttrs->valign &&
118119 textAlignChar == otherAttrs->textAlignChar &&
120 textTransform == otherAttrs->textTransform &&
119121 hBorderSpacing == otherAttrs->hBorderSpacing &&
120122 vBorderSpacing == otherAttrs->vBorderSpacing &&
121123 wordSpacing == otherAttrs->wordSpacing &&
153155 textAlign +
154156 valign +
155157 textAlignChar +
158 textTransform +
156159 hBorderSpacing +
157160 vBorderSpacing +
158161 wordSpacing +
243246 textAlign = attrs->textAlign;
244247 valign = attrs->valign;
245248 textAlignChar = attrs->textAlignChar;
249 textTransform = attrs->textTransform;
246250 hBorderSpacing = attrs->hBorderSpacing;
247251 vBorderSpacing = attrs->vBorderSpacing;
248252 wordSpacing = attrs->wordSpacing;
884888 *const roman_I2[] = { "","C","CC","CCC","CD","D","DC","DCC","DCCC","CM" },
885889 *const roman_I3[] = { "","M","MM","MMM","MMMM" };
886890
887 static void strtolower (char *s)
891 static void strAsciiTolower (char *s)
888892 {
889893 for ( ; *s; s++)
890 *s = tolower (*s);
894 *s = misc::AsciiTolower (*s);
891895 }
892896
893897 /**
942946 buf[buflen - 1] = '\0';
943947
944948 if (low)
945 strtolower(buf);
949 strAsciiTolower(buf);
946950
947951 }
948952
244244 VALIGN_SUPER,
245245 VALIGN_TEXT_TOP,
246246 VALIGN_TEXT_BOTTOM,
247 };
248
249 enum TextTransform {
250 TEXT_TRANSFORM_NONE,
251 TEXT_TRANSFORM_CAPITALIZE,
252 TEXT_TRANSFORM_UPPERCASE,
253 TEXT_TRANSFORM_LOWERCASE,
247254 };
248255
249256 /**
440447 TextAlignType textAlign;
441448 VAlignType valign;
442449 char textAlignChar; /* In future, strings will be supported. */
450 TextTransform textTransform;
443451
444452 int hBorderSpacing, vBorderSpacing, wordSpacing;
445453 Length width, height, lineHeight, textIndent;
269269
270270 void Table::addCell (Widget *widget, int colspan, int rowspan)
271271 {
272 const int maxspan = 100;
272273 Child *child;
273274 int colspanEff;
274275
275 // We limit the values for colspan and rowspan to 50, to avoid
276 // We limit the values for colspan and rowspan to avoid
276277 // attacks by malicious web pages.
277 if (colspan > 50 || colspan < 0) {
278 MSG_WARN("colspan = %d is set to 50.\n", colspan);
279 colspan = 50;
280 }
281 if (rowspan > 50 || rowspan <= 0) {
282 MSG_WARN("rowspan = %d is set to 50.\n", rowspan);
283 rowspan = 50;
278 if (colspan > maxspan || colspan < 0) {
279 MSG_WARN("colspan = %d is set to %d.\n", colspan, maxspan);
280 colspan = maxspan;
281 }
282 if (rowspan > maxspan || rowspan <= 0) {
283 MSG_WARN("rowspan = %d is set to %d.\n", rowspan, maxspan);
284 rowspan = maxspan;
284285 }
285286
286287 if (numRows == 0) {
6969 words = new misc::SimpleVector <Word> (1);
7070 anchors = new misc::SimpleVector <Anchor> (1);
7171
72 //DBG_OBJ_SET_NUM(page, "num_lines", num_lines);
72 //DBG_OBJ_SET_NUM(this, "num_lines", num_lines);
7373
7474 lastLineWidth = 0;
75 lastLineParMin = 0;
7675 lastLineParMax = 0;
7776 wrapRef = -1;
7877
79 //DBG_OBJ_SET_NUM(page, "last_line_width", last_line_width);
80 //DBG_OBJ_SET_NUM(page, "last_line_par_min", last_line_par_min);
81 //DBG_OBJ_SET_NUM(page, "last_line_par_max", last_line_par_max);
82 //DBG_OBJ_SET_NUM(page, "wrap_ref", wrap_ref);
78 //DBG_OBJ_SET_NUM(this, "last_line_width", last_line_width);
79 //DBG_OBJ_SET_NUM(this, "last_line_par_min", last_line_par_min);
80 //DBG_OBJ_SET_NUM(this, "last_line_par_max", last_line_par_max);
81 //DBG_OBJ_SET_NUM(this, "wrap_ref", wrap_ref);
8382
8483 hoverLink = -1;
8584
128127 parent class destructor. (???) */
129128 words = NULL;
130129
131 //DBG_OBJ_SET_NUM(page, "num_lines", page->num_lines);
130 //DBG_OBJ_SET_NUM(this, "num_lines", lines->size ());
132131 }
133132
134133 /**
201200 {
202201 core::Extremes wordExtremes;
203202 Line *line;
204 Word *word;
203 Word *word, *prevWord = NULL;
205204 int wordIndex, lineIndex;
206 int parMin, parMax;
207 bool nowrap;
208
209 //DBG_MSG (widget, "extremes", 0, "Dw_page_get_extremes");
205 int parMax;
206
207 //DBG_MSG (widget, "extremes", 0, "getExtremesImpl");
210208 //DBG_MSG_START (widget);
211209
212210 if (lines->size () == 0) {
216214 } else if (wrapRef == -1) {
217215 /* no rewrap necessary -> values in lines are up to date */
218216 line = lines->getRef (lines->size () - 1);
219 /* Historical note: The former distinction between lines with and without
220 * words[first_word]->nowrap set is no longer necessary, since
221 * Dw_page_real_word_wrap sets max_word_min to the correct value in any
222 * case. */
223 extremes->minWidth = line->maxWordMin;
217 extremes->minWidth = line->maxParMin;
224218 extremes->maxWidth = misc::max (line->maxParMax, lastLineParMax);
225219 //DBG_MSG (widget, "extremes", 0, "simple case");
226220 } else {
231225 if (wrapRef == 0) {
232226 extremes->minWidth = 0;
233227 extremes->maxWidth = 0;
234 parMin = 0;
235228 parMax = 0;
236229 } else {
237230 line = lines->getRef (wrapRef);
238 extremes->minWidth = line->maxWordMin;
231 extremes->minWidth = line->maxParMin;
239232 extremes->maxWidth = line->maxParMax;
240 parMin = line->parMin;
241233 parMax = line->parMax;
242234
243235 //DBG_MSGF (widget, "extremes", 0, "parMin = %d", parMin);
249241 for (lineIndex = wrapRef; lineIndex < lines->size (); lineIndex++) {
250242 //DBG_MSGF (widget, "extremes", 0, "line %d", lineIndex);
251243 //DBG_MSG_START (widget);
252 core::style::WhiteSpace ws;
244 int parMin = 0;
253245
254246 line = lines->getRef (lineIndex);
255 ws = words->getRef(line->firstWord)->style->whiteSpace;
256 nowrap = ws == core::style::WHITE_SPACE_PRE ||
257 ws == core::style::WHITE_SPACE_NOWRAP;
258
259 //DEBUG_MSG (DEBUG_SIZE_LEVEL, " line %d (of %d), nowrap = %d\n",
260 // lineIndex, page->num_lines, nowrap);
261247
262248 for (wordIndex = line->firstWord; wordIndex <= line->lastWord;
263249 wordIndex++) {
268254 wordExtremes.minWidth += line1OffsetEff;
269255 wordExtremes.maxWidth += line1OffsetEff;
270256 //DEBUG_MSG (DEBUG_SIZE_LEVEL + 1,
271 // " (next plus %d)\n", page->line1_offset);
257 // " (next plus %d)\n", line1OffsetEff);
272258 }
273259
274 if (nowrap) {
275 parMin += prevWordSpace + wordExtremes.minWidth;
276 //DBG_MSGF (widget, "extremes", 0, "parMin = %d", parMin);
277 } else {
278 if (extremes->minWidth < wordExtremes.minWidth)
279 extremes->minWidth = wordExtremes.minWidth;
280 }
260
261 if (extremes->minWidth < wordExtremes.minWidth)
262 extremes->minWidth = wordExtremes.minWidth;
281263
282264 _MSG("parMax = %d, wordMaxWidth=%d, prevWordSpace=%d\n",
283265 parMax, wordExtremes.maxWidth, prevWordSpace);
284266 if (word->content.type != core::Content::BREAK)
285267 parMax += prevWordSpace;
286268 parMax += wordExtremes.maxWidth;
269
270 if (prevWord && !canBreakAfter(prevWord)) {
271 parMin += prevWordSpace + wordExtremes.minWidth;
272 } else {
273 parMin = wordExtremes.minWidth;
274 }
275
276 if (extremes->minWidth < parMin) {
277 extremes->minWidth = parMin;
278 }
279
287280 prevWordSpace = word->origSpace;
281 prevWord = word;
288282
289283 //DEBUG_MSG (DEBUG_SIZE_LEVEL + 1,
290284 // " word %s: maxWidth = %d\n",
291 // a_Dw_content_text (&word->content),
285 // word->content.text,
292286 // word_extremes.maxWidth);
293287 }
294288
299293 //DEBUG_MSG (DEBUG_SIZE_LEVEL + 2,
300294 // " parMax = %d, after word %d (%s)\n",
301295 // parMax, line->last_word - 1,
302 // a_Dw_content_text (&word->content));
296 // word->content.text);
303297
304298 if (extremes->maxWidth < parMax)
305299 extremes->maxWidth = parMax;
306300
307 if (nowrap) {
308 //DBG_MSGF (widget, "extremes", 0, "parMin = %d", parMin);
309 if (extremes->minWidth < parMin)
310 extremes->minWidth = parMin;
311
312 //DEBUG_MSG (DEBUG_SIZE_LEVEL + 2,
313 // " parMin = %d, after word %d (%s)\n",
314 // parMin, line->last_word - 1,
315 // a_Dw_content_text (&word->content));
316 }
317
318301 prevWordSpace = 0;
319 parMin = 0;
320302 parMax = 0;
321303 }
322304
328310 }
329311
330312 //DBG_MSGF (widget, "extremes", 0, "width difference: %d + %d",
331 // page->inner_padding, p_Dw_style_box_diff_width (widget->style));
313 // innerPadding, getStyle()->boxDiffWidth ());
332314
333315 int diff = innerPadding + getStyle()->boxDiffWidth ();
334316 extremes->minWidth += diff;
479461 void Textblock::markChange (int ref)
480462 {
481463 if (ref != -1) {
482 //DBG_MSGF (page, "wrap", 0, "Dw_page_mark_size_change (ref = %d)", ref);
464 //DBG_MSGF (page, "wrap", 0, "markChange (ref = %d)", ref);
483465
484466 if (wrapRef == -1)
485467 wrapRef = ref;
486468 else
487469 wrapRef = misc::min (wrapRef, ref);
488470
489 //DBG_OBJ_SET_NUM (page, "wrap_ref", page->wrap_ref);
471 //DBG_OBJ_SET_NUM (this, "wrap_ref", wrapRef);
490472 }
491473 }
492474
493475 void Textblock::setWidth (int width)
494476 {
495 /* If limitTextWidth is set to YES, a queue_resize may also be
477 /* If limitTextWidth is set to YES, a queueResize() may also be
496478 * necessary. */
497479 if (availWidth != width || limitTextWidth) {
498480 //DEBUG_MSG(DEBUG_REWRAP_LEVEL,
499 // "Dw_page_set_width: Calling p_Dw_widget_queue_resize, "
481 // "setWidth: Calling queueResize, "
500482 // "in page with %d word(s)\n",
501 // page->num_words);
483 // words->size());
502484
503485 availWidth = width;
504486 queueResize (0, false);
511493 {
512494 if (availAscent != ascent) {
513495 //DEBUG_MSG(DEBUG_REWRAP_LEVEL,
514 // "Dw_page_set_ascent: Calling p_Dw_widget_queue_resize, "
496 // "setAscent: Calling queueResize, "
515497 // "in page with %d word(s)\n",
516 // page->num_words);
498 // words->size());
517499
518500 availAscent = ascent;
519501 queueResize (0, false);
525507 {
526508 if (availDescent != descent) {
527509 //DEBUG_MSG(DEBUG_REWRAP_LEVEL,
528 // "Dw_page_set_descent: Calling p_Dw_widget_queue_resize, "
510 // "setDescent: Calling queueResize, "
529511 // "in page with %d word(s)\n",
530 // page->num_words);
512 // words->size());
531513
532514 availDescent = descent;
533515 queueResize (0, false);
620602 core::MousePositionEvent *event)
621603 {
622604 core::Iterator *it;
623 Line *line, *lastLine;
624 int nextWordStartX, wordStartX, wordX, nextWordX, yFirst, yLast;
625 int charPos = 0, link = -1, prevPos, wordIndex, lineIndex;
626 Word *word;
627 bool found, r;
605 int wordIndex;
606 int charPos = 0, link = -1;
607 bool r;
628608
629609 if (words->size () == 0) {
630610 wordIndex = -1;
631611 } else {
632 lastLine = lines->getRef (lines->size () - 1);
633 yFirst = lineYOffsetCanvasI (0);
634 yLast = lineYOffsetCanvas (lastLine) + lastLine->boxAscent +
635 lastLine->boxDescent;
612 Line *lastLine = lines->getRef (lines->size () - 1);
613 int yFirst = lineYOffsetCanvasI (0);
614 int yLast = lineYOffsetCanvas (lastLine) + lastLine->boxAscent +
615 lastLine->boxDescent;
636616 if (event->yCanvas < yFirst) {
637617 // Above the first line: take the first word.
638618 wordIndex = 0;
639 charPos = 0;
640619 } else if (event->yCanvas >= yLast) {
641620 // Below the last line: take the last word.
642621 wordIndex = words->size () - 1;
643 word = words->getRef (wordIndex);
644 charPos = word->content.type == core::Content::TEXT ?
645 strlen (word->content.text) : 0;
622 charPos = core::SelectionState::END_OF_WORD;
646623 } else {
647 lineIndex = findLineIndex (event->yWidget);
648 line = lines->getRef (lineIndex);
624 Line *line = lines->getRef (findLineIndex (event->yWidget));
649625
650626 // Pointer within the break space?
651627 if (event->yWidget >
652628 (lineYOffsetWidget (line) + line->boxAscent + line->boxDescent)) {
653629 // Choose this break.
654630 wordIndex = line->lastWord;
655 charPos = 0;
631 charPos = core::SelectionState::END_OF_WORD;
656632 } else if (event->xWidget < lineXOffsetWidget (line)) {
657633 // Left of the first word in the line.
658634 wordIndex = line->firstWord;
659 charPos = 0;
660635 } else {
661 nextWordStartX = lineXOffsetWidget (line);
662 found = false;
636 int nextWordStartX = lineXOffsetWidget (line);
637
663638 for (wordIndex = line->firstWord;
664 !found && wordIndex <= line->lastWord;
639 wordIndex <= line->lastWord;
665640 wordIndex++) {
666 word = words->getRef (wordIndex);
667 wordStartX = nextWordStartX;
641 Word *word = words->getRef (wordIndex);
642 int wordStartX = nextWordStartX;
643
668644 nextWordStartX += word->size.width + word->effSpace;
669645
670646 if (event->xWidget >= wordStartX &&
671647 event->xWidget < nextWordStartX) {
672648 // We have found the word.
673 if (word->content.type == core::Content::TEXT) {
674 // Search the character the mouse pointer is in.
675 // nextWordX is the right side of this character.
676 charPos = 0;
677 while ((nextWordX = wordStartX +
678 layout->textWidth (word->style->font,
679 word->content.text, charPos))
680 <= event->xWidget)
681 charPos = layout->nextGlyph (word->content.text,
682 charPos);
683 // The left side of this character.
684 prevPos = layout->prevGlyph (word->content.text, charPos);
685 wordX = wordStartX + layout->textWidth (word->style->font,
686 word->content.text,
687 prevPos);
688
689 // If the mouse pointer is left from the middle, use the
690 // left position, otherwise, use the right one.
691 if (event->xWidget <= (wordX + nextWordX) / 2)
692 charPos = prevPos;
649 int yWidgetBase = lineYOffsetWidget (line) + line->boxAscent;
650
651 if (event->xWidget >= nextWordStartX - word->effSpace) {
652 charPos = core::SelectionState::END_OF_WORD;
653 if (wordIndex < line->lastWord &&
654 (words->getRef(wordIndex + 1)->content.type !=
655 core::Content::BREAK) &&
656 (event->yWidget <=
657 yWidgetBase + word->spaceStyle->font->descent) &&
658 (event->yWidget >
659 yWidgetBase - word->spaceStyle->font->ascent)) {
660 link = word->spaceStyle->x_link;
661 }
693662 } else {
694 // Depends on whether the pointer is within the left or
695 // right half of the (non-text) word.
696 if (event->xWidget >=
697 (wordStartX + nextWordStartX) / 2)
698 charPos = core::SelectionState::END_OF_WORD;
699 else
700 charPos = 0;
663 if (event->yWidget <= yWidgetBase + word->size.descent &&
664 event->yWidget > yWidgetBase - word->size.ascent) {
665 link = word->style->x_link;
666 }
667 if (word->content.type == core::Content::TEXT) {
668 int glyphX = wordStartX;
669
670 while (1) {
671 int nextCharPos =
672 layout->nextGlyph (word->content.text, charPos);
673 int glyphWidth =
674 textWidth (word->content.text, charPos,
675 nextCharPos - charPos, word->style);
676 if (event->xWidget > glyphX + glyphWidth) {
677 glyphX += glyphWidth;
678 charPos = nextCharPos;
679 continue;
680 } else if (event->xWidget >= glyphX + glyphWidth/2){
681 // On the right half of a character;
682 // now just look for combining chars
683 charPos = nextCharPos;
684 while (word->content.text[charPos]) {
685 nextCharPos =
686 layout->nextGlyph (word->content.text,
687 charPos);
688 if (textWidth (word->content.text, charPos,
689 nextCharPos - charPos,
690 word->style))
691 break;
692 charPos = nextCharPos;
693 }
694 }
695 break;
696 }
697 } else {
698 // Depends on whether the pointer is within the left or
699 // right half of the (non-text) word.
700 if (event->xWidget >= (wordStartX + nextWordStartX) /2)
701 charPos = core::SelectionState::END_OF_WORD;
702 }
701703 }
702
703 found = true;
704 link = word->style ? word->style->x_link : -1;
705704 break;
706705 }
707706 }
708
709 if (!found) {
707 if (wordIndex > line->lastWord) {
710708 // No word found in this line (i.e. we are on the right side),
711709 // take the last of this line.
712710 wordIndex = line->lastWord;
713 if (wordIndex >= words->size ())
714 wordIndex--;
715 word = words->getRef (wordIndex);
716 charPos = word->content.type == core::Content::TEXT ?
717 strlen (word->content.text) :
718 (int)core::SelectionState::END_OF_WORD;
711 charPos = core::SelectionState::END_OF_WORD;
719712 }
720713 }
721714 }
769762
770763 words->getRef(i)->effSpace = words->getRef(i)->origSpace +
771764 (effSpaceDiffCum - lastEffSpaceDiffCum);
772 //DBG_OBJ_ARRSET_NUM (page, "words.%d.eff_space", i,
773 // page->words[i].eff_space);
765 //DBG_OBJ_ARRSET_NUM (this, "words.%d.effSpace", i,
766 // words->getRef(i)->effSpace);
774767
775768 lastEffSpaceDiffCum = effSpaceDiffCum;
776769 }
782775 {
783776 Line *lastLine;
784777
785 //DBG_MSG (page, "wrap", 0, "Dw_page_add_line");
778 //DBG_MSG (page, "wrap", 0, "addLine");
786779 //DBG_MSG_START (page);
787780
788781 lines->increase ();
789 //DBG_OBJ_SET_NUM(page, "num_lines", page->num_lines);
782 //DBG_OBJ_SET_NUM(this, "num_lines", lines->size ());
790783
791784 //DEBUG_MSG (DEBUG_REWRAP_LEVEL, "--- new line %d in %p, with word %d of %d"
792 // "\n", page->num_lines - 1, page, word_ind, page->num_words);
785 // "\n", lines->size () - 1, page, word_ind, words->size());
793786
794787 lastLine = lines->getRef (lines->size () - 1);
795788
796789 if (lines->size () == 1) {
797790 lastLine->top = 0;
798791 lastLine->maxLineWidth = line1OffsetEff;
799 lastLine->maxWordMin = 0;
792 lastLine->maxParMin = 0;
800793 lastLine->maxParMax = 0;
801794 } else {
802795 Line *prevLine = lines->getRef (lines->size () - 2);
804797 lastLine->top = prevLine->top + prevLine->boxAscent +
805798 prevLine->boxDescent + prevLine->breakSpace;
806799 lastLine->maxLineWidth = prevLine->maxLineWidth;
807 lastLine->maxWordMin = prevLine->maxWordMin;
800 lastLine->maxParMin = prevLine->maxParMin;
808801 lastLine->maxParMax = prevLine->maxParMax;
809802 }
810803
811 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.top", page->num_lines - 1,
804 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.top", lines->size () - 1,
812805 // lastLine->top);
813 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.maxLineWidth", page->num_lines - 1,
806 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.maxLineWidth", lines->size () - 1,
814807 // lastLine->maxLineWidth);
815 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.maxWordMin", page->num_lines - 1,
816 // lastLine->maxWordMin);
817 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.maxParMax", page->num_lines - 1,
808 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.maxParMin", lines->size () - 1,
809 // lastLine->maxParMin);
810 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.maxParMax", lines->size () - 1,
818811 // lastLine->maxParMax);
819 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.parMin", page->num_lines - 1,
812 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.parMin", lines->size () - 1,
820813 // lastLine->parMin);
821 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.parMax", page->num_lines - 1,
814 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.parMax", lines->size () - 1,
822815 // lastLine->parMax);
823816
824817 lastLine->firstWord = wordIndex;
828821 lastLine->breakSpace = 0;
829822 lastLine->leftOffset = 0;
830823
831 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.ascent", page->num_lines - 1,
824 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.ascent", lines->size () - 1,
832825 // lastLine->boxAscent);
833 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.descent", page->num_lines - 1,
826 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.descent", lines->size () - 1,
834827 // lastLine->boxDescent);
835828
836829 /* update values in line */
843836
844837 if (newPar) {
845838 lastLine->maxParMax = misc::max (lastLine->maxParMax, lastLineParMax);
846 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.maxParMax", page->num_lines - 1,
839 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.maxParMax", lines->size () - 1,
847840 // lastLine->maxParMax);
848841
849 /* The following code looks questionable (especially since the values
850 * will be overwritten). In any case, line1OffsetEff is probably
851 * supposed to go into lastLinePar*, not lastLine->par*.
852 */
853842 if (lines->size () > 1) {
854 lastLine->parMin = 0;
855 lastLine->parMax = 0;
843 lastLineParMax = 0;
856844 } else {
857 lastLine->parMin = line1OffsetEff;
858 lastLine->parMax = line1OffsetEff;
859 }
860 lastLineParMin = 0;
861 lastLineParMax = 0;
862
863 //DBG_OBJ_SET_NUM(page, "lastLineParMin", page->lastLineParMin);
864 //DBG_OBJ_SET_NUM(page, "lastLineParMax", page->lastLineParMax);
865 }
866
867 lastLine->parMin = lastLineParMin;
845 lastLineParMax = line1OffsetEff;
846 }
847
848 //DBG_OBJ_SET_NUM(this, "lastLineParMax", lastLineParMax);
849 }
850
868851 lastLine->parMax = lastLineParMax;
869852
870 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.parMin", page->num_lines - 1,
853 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.parMin", lines->size () - 1,
871854 // lastLine->parMin);
872 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.parMax", page->num_lines - 1,
855 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.parMax", lines->size () - 1,
873856 // lastLine->parMax);
874857
875858 //DBG_MSG_END (page);
886869 Line *lastLine;
887870 Word *word;
888871 int availWidth, lastSpace, leftOffset, len;
889 bool newLine = false, newPar = false;
872 bool newLine = false, newPar = false, canBreakBefore = true;
890873 core::Extremes wordExtremes;
891874
892 //DBG_MSGF (page, "wrap", 0, "Dw_page_real_word_wrap (%d): %s, width = %d",
893 // word_ind, a_Dw_content_html (&page->words[word_ind].content),
894 // page->words[word_ind].size.width);
875 //DBG_MSGF (page, "wrap", 0, "wordWrap (%d): %s, width = %d",
876 // wordIndex, words->getRef(wordIndex)->content.text),
877 // words->getRef(wordIndex)->size.width);
895878 //DBG_MSG_START (page);
896879
897880 availWidth = this->availWidth - getStyle()->boxDiffWidth() - innerPadding;
941924 /* previous word is a break */
942925 newLine = true;
943926 newPar = true;
944 } else if (word->style->whiteSpace == core::style::WHITE_SPACE_NOWRAP ||
945 word->style->whiteSpace == core::style::WHITE_SPACE_PRE) {
946 //DBG_MSGF (page, "wrap", 0, "no wrap (white_space = %d)",
947 // word->style->white_space);
927 } else if (!canBreakAfter (prevWord)) {
928 canBreakBefore = false;
929 // no break within nowrap
948930 newLine = false;
949931 newPar = false;
932 if (lastLineWidth + prevWord->origSpace + word->size.width >
933 availWidth)
934 markChange (lines->size () - 1);
950935 } else if (lastLine->firstWord != wordIndex) {
951 /* Does new word fit into the last line? */
952 //DBG_MSGF (page, "wrap", 0,
953 // "word %d (%s) fits? (%d + %d + %d &lt;= %d)...",
954 // word_ind, a_Dw_content_html (&word->content),
955 // page->lastLine_width, prevWord->orig_space,
956 // word->size.width, availWidth);
957 newLine = lastLineWidth + prevWord->origSpace + word->size.width >
958 availWidth;
959 //DBG_MSGF (page, "wrap", 0, "... %s.",
960 // newLine ? "No" : "Yes");
936 // check if we need to break because nowrap sequence is following
937 newLine = false;
938 int lineWidthNeeded = lastLineWidth + prevWord->origSpace;
939 for (int i = wordIndex; i < words->size (); i++) {
940 Word *w = words->getRef (i);
941
942 if (w->content.type == core::Content::BREAK ||
943 (word->content.type == core::Content::WIDGET &&
944 word->content.widget->blockLevel()))
945 break;
946
947 lineWidthNeeded += w->size.width;
948
949 if (lineWidthNeeded > availWidth) {
950 newLine = true;
951 break;
952 } else if (canBreakAfter (w)) {
953 break;
954 }
955
956 lineWidthNeeded += w->origSpace;
957 }
961958 }
962959 }
963960
983980 len += word->style->font->ascent / 3;
984981 lastLine->contentDescent = misc::max (lastLine->contentDescent, len);
985982
986 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.ascent", page->num_lines - 1,
983 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.ascent", lines->size () - 1,
987984 // lastLine->boxAscent);
988 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.descent", page->num_lines - 1,
985 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.descent", lines->size () - 1,
989986 // lastLine->boxDescent);
990987
991988 if (word->content.type == core::Content::WIDGET) {
1000997 word->content.widget->blockLevel () &&
1001998 getStyle ()->borderWidth.top == 0 &&
1002999 getStyle ()->padding.top == 0) {
1003 // collapse top margin of parent element with top margin of first child
1000 // collapse top margins of parent element and its first child
10041001 // see: http://www.w3.org/TR/CSS21/box.html#collapsing-margins
10051002 collapseMarginTop = getStyle ()->margin.top;
10061003 }
10281025 if (!newLine)
10291026 lastLineWidth += lastSpace;
10301027 if (!newPar) {
1031 lastLineParMin += lastSpace;
10321028 lastLineParMax += lastSpace;
10331029 }
10341030
10351031 lastLineWidth += word->size.width;
10361032
10371033 getWordExtremes (word, &wordExtremes);
1038 lastLineParMin += wordExtremes.maxWidth; /* Why maxWidth? */
10391034 lastLineParMax += wordExtremes.maxWidth;
10401035
1041 if (word->style->whiteSpace == core::style::WHITE_SPACE_NOWRAP ||
1042 word->style->whiteSpace == core::style::WHITE_SPACE_PRE) {
1043 lastLine->parMin += wordExtremes.minWidth + lastSpace;
1036 if (!canBreakBefore) {
1037 lastLineParMin += wordExtremes.minWidth + lastSpace;
10441038 /* This may also increase the accumulated minimum word width. */
1045 lastLine->maxWordMin =
1046 misc::max (lastLine->maxWordMin, lastLine->parMin);
1047 /* NOTE: Most code relies on that all values of nowrap are equal for all
1048 * words within one line. */
1039 lastLine->maxParMin = misc::max (lastLine->maxParMin, lastLineParMin);
10491040 } else {
1050 lastLine->maxWordMin =
1051 misc::max (lastLine->maxWordMin, wordExtremes.minWidth);
1052 }
1053
1054 //DBG_OBJ_SET_NUM(page, "lastLine_par_min", page->lastLine_par_min);
1055 //DBG_OBJ_SET_NUM(page, "lastLine_par_max", page->lastLine_par_max);
1056 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.par_min", page->num_lines - 1,
1041 lastLineParMin = wordExtremes.minWidth;
1042 lastLine->maxParMin =
1043 misc::max (lastLine->maxParMin, wordExtremes.minWidth);
1044 }
1045
1046 //DBG_OBJ_SET_NUM(this, "lastLine_par_min", lastLineParMin);
1047 //DBG_OBJ_SET_NUM(this, "lastLine_par_max", lastLineParMax);
1048 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.par_min", lines->size () - 1,
10571049 // lastLine->par_min);
1058 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.par_max", page->num_lines - 1,
1050 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.par_max", lines->size () - 1,
10591051 // lastLine->par_max);
1060 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.max_word_min", page->num_lines - 1,
1052 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.max_word_min", lines->size () - 1,
10611053 // lastLine->max_word_min);
10621054
10631055 /* Align the line.
10861078 if (leftOffset < 0)
10871079 leftOffset = 0;
10881080
1089 if (hasListitemValue && lastLine == lines->getRef (0)) {
1090 /* List item markers are always on the left. */
1091 lastLine->leftOffset = 0;
1092 words->getRef(0)->effSpace = words->getRef(0)->origSpace + leftOffset;
1093 //DBG_OBJ_ARRSET_NUM (page, "words.%d.eff_space", 0,
1094 // page->words[0].eff_space);
1095 } else {
1096 lastLine->leftOffset = leftOffset;
1097 }
1081 lastLine->leftOffset = leftOffset;
10981082 }
10991083 mustQueueResize = true;
11001084
11761160 return;
11771161
11781162 //DBG_MSGF (page, "wrap", 0,
1179 // "Dw_page_rewrap: page->wrap_ref = %d, in page with %d word(s)",
1180 // page->wrap_ref, page->num_words);
1163 // "rewrap: wrapRef = %d, in page with %d word(s)",
1164 // wrapRef, words->size());
11811165 //DBG_MSG_START (page);
11821166
1183 /* All lines up from page->wrap_ref will be rebuild from the word list,
1167 /* All lines up from wrapRef will be rebuild from the word list,
11841168 * the line list up from this position is rebuild. */
11851169 lines->setSize (wrapRef);
11861170 lastLineWidth = 0;
1187 //DBG_OBJ_SET_NUM(page, "num_lines", page->num_lines);
1188 //DBG_OBJ_SET_NUM(page, "lastLine_width", page->lastLine_width);
1171 lastLineParMin = 0;
1172 //DBG_OBJ_SET_NUM(this, "num_lines", lines->size ());
1173 //DBG_OBJ_SET_NUM(this, "lastLine_width", lastLineWidth);
11891174
11901175 /* In the word list, start at the last word plus one in the line before. */
11911176 if (wrapRef > 0) {
1192 /* Note: In this case, Dw_page_real_word_wrap will immediately find
1193 * the need to rewrap the line, since we start with the last one (plus
1194 * one). This is also the reason, why page->lastLine_width is set
1177 /* Note: In this case, wordWrap() will immediately find the need
1178 * to rewrap the line, since we start with the last one (plus one).
1179 * This is also the reason, why lastLineWidth is set
11951180 * to the length of the line. */
11961181 lastLine = lines->getRef (lines->size () - 1);
11971182
1198 lastLineParMin = lastLine->parMin;
11991183 lastLineParMax = lastLine->parMax;
12001184
12011185 wordIndex = lastLine->lastWord + 1;
12041188 words->getRef(i)->origSpace);
12051189 lastLineWidth += words->getRef(lastLine->lastWord)->size.width;
12061190 } else {
1207 lastLineParMin = 0;
12081191 lastLineParMax = 0;
12091192
12101193 wordIndex = 0;
12261209 //DEBUG_MSG(DEBUG_REWRAP_LEVEL,
12271210 // "Assigning parent_ref = %d to rewrapped word %d, "
12281211 // "in page with %d word(s)\n",
1229 // page->num_lines - 1, wordIndex, page->num_words);
1212 // lines->size () - 1, wordIndex, words->size());
12301213
12311214 /* todo_refactoring:
12321215 if (word->content.type == DW_CONTENT_ANCHOR)
12331216 p_Dw_gtk_viewport_change_anchor
12341217 (widget, word->content.anchor,
12351218 Dw_page_line_total_y_offset (page,
1236 &page->lines[page->num_lines - 1]));
1219 &page->lines[lines->size () - 1]));
12371220 */
12381221 }
12391222
12691252 }
12701253
12711254 /*
1255 * Draw a string of text
1256 */
1257 void Textblock::drawText(core::View *view, core::style::Style *style,
1258 core::style::Color::Shading shading, int x, int y,
1259 const char *text, int start, int len)
1260 {
1261 if (len > 0) {
1262 char *str = NULL;
1263
1264 switch (style->textTransform) {
1265 case core::style::TEXT_TRANSFORM_NONE:
1266 default:
1267 break;
1268 case core::style::TEXT_TRANSFORM_UPPERCASE:
1269 str = layout->textToUpper(text + start, len);
1270 break;
1271 case core::style::TEXT_TRANSFORM_LOWERCASE:
1272 str = layout->textToLower(text + start, len);
1273 break;
1274 case core::style::TEXT_TRANSFORM_CAPITALIZE:
1275 {
1276 /* \bug No way to know about non-ASCII punctuation. */
1277 bool initial_seen = false;
1278
1279 for (int i = 0; i < start; i++)
1280 if (!ispunct(text[i]))
1281 initial_seen = true;
1282 if (initial_seen)
1283 break;
1284
1285 int after = 0;
1286 text += start;
1287 while (ispunct(text[after]))
1288 after++;
1289 if (text[after])
1290 after = layout->nextGlyph(text, after);
1291 if (after > len)
1292 after = len;
1293
1294 char *initial = layout->textToUpper(text, after);
1295 int newlen = strlen(initial) + len-after;
1296 str = (char *)malloc(newlen + 1);
1297 strcpy(str, initial);
1298 strncpy(str + strlen(str), text+after, len-after);
1299 str[newlen] = '\0';
1300 free(initial);
1301 break;
1302 }
1303 }
1304 view->drawText(style->font, style->color, shading, x, y,
1305 str ? str : text + start, str ? strlen(str) : len);
1306 if (str)
1307 free(str);
1308 }
1309 }
1310
1311 /*
12721312 * Draw a word of text.
12731313 */
1274 void Textblock::drawText(int wordIndex, core::View *view,core::Rectangle *area,
1314 void Textblock::drawWord(int wordIndex, core::View *view,core::Rectangle *area,
12751315 int xWidget, int yWidgetBase)
12761316 {
12771317 Word *word = words->getRef(wordIndex);
12871327 }
12881328 yWorldBase = yWidgetBase + allocation.y;
12891329
1290 view->drawText (style->font, style->color,
1291 core::style::Color::SHADING_NORMAL, xWorld, yWorldBase,
1292 word->content.text, strlen (word->content.text));
1330 drawText (view, style, core::style::Color::SHADING_NORMAL, xWorld,
1331 yWorldBase, word->content.text, 0, strlen (word->content.text));
12931332
12941333 if (style->textDecoration)
12951334 decorateText(view, style, core::style::Color::SHADING_NORMAL, xWorld,
13111350
13121351 xStart = xWorld;
13131352 if (firstCharIdx)
1314 xStart += layout->textWidth (style->font, word->content.text,
1315 firstCharIdx);
1353 xStart += textWidth (word->content.text, 0, firstCharIdx, style);
13161354 if (firstCharIdx == 0 && lastCharIdx == wordLen)
13171355 width = word->size.width;
13181356 else
1319 width = layout->textWidth (style->font,
1320 word->content.text + firstCharIdx,
1321 lastCharIdx - firstCharIdx);
1357 width = textWidth (word->content.text, firstCharIdx,
1358 lastCharIdx - firstCharIdx, style);
13221359 if (width > 0) {
13231360 /* Highlight text */
13241361 core::style::Color *wordBgColor;
13331370 style->font->ascent + style->font->descent);
13341371
13351372 /* Highlight the text. */
1336 view->drawText (style->font, style->color,
1337 core::style::Color::SHADING_INVERSE, xStart,
1338 yWorldBase, word->content.text + firstCharIdx,
1339 lastCharIdx - firstCharIdx);
1373 drawText (view, style, core::style::Color::SHADING_INVERSE, xStart,
1374 yWorldBase, word->content.text, firstCharIdx,
1375 lastCharIdx - firstCharIdx);
13401376
13411377 if (style->textDecoration)
13421378 decorateText(view, style, core::style::Color::SHADING_INVERSE,
14341470 yWidgetBase - line->boxAscent, word->size.width,
14351471 line->boxAscent + line->boxDescent, false);
14361472 }
1437 drawText(wordIndex, view, area, xWidget, yWidgetBase);
1473 drawWord(wordIndex, view, area, xWidget, yWidgetBase);
14381474 }
14391475 }
14401476 if (word->effSpace > 0 && wordIndex < line->lastWord &&
15341570 word = words->getRef (wordIndex);
15351571 lastXCursor = xCursor;
15361572 xCursor += word->size.width + word->effSpace;
1537 if (lastXCursor <= x && xCursor > x &&
1538 y > yWidgetBase - word->size.ascent &&
1539 y <= yWidgetBase + word->size.descent) {
1540 *inSpace = x >= xCursor - word->effSpace;
1541 return word;
1573 if (lastXCursor <= x && xCursor > x) {
1574 if (x >= xCursor - word->effSpace) {
1575 if (wordIndex < line->lastWord &&
1576 (words->getRef(wordIndex + 1)->content.type !=
1577 core::Content::BREAK) &&
1578 y > yWidgetBase - word->spaceStyle->font->ascent &&
1579 y <= yWidgetBase + word->spaceStyle->font->descent) {
1580 *inSpace = true;
1581 return word;
1582 }
1583 } else {
1584 if (y > yWidgetBase - word->size.ascent &&
1585 y <= yWidgetBase + word->size.descent)
1586 return word;
1587 }
1588 break;
15421589 }
15431590 }
15441591
15801627 word->origSpace = 0;
15811628 word->effSpace = 0;
15821629 word->content.space = false;
1583
1584 //DBG_OBJ_ARRSET_NUM (page, "words.%d.size.width", page->num_words - 1,
1630 word->content.breakType = core::Content::BREAK_NO;
1631
1632 //DBG_OBJ_ARRSET_NUM (this, "words.%d.size.width", words->size() - 1,
15851633 // word->size.width);
1586 //DBG_OBJ_ARRSET_NUM (page, "words.%d.size.descent", page->num_words - 1,
1634 //DBG_OBJ_ARRSET_NUM (this, "words.%d.size.descent", words->size() - 1,
15871635 // word->size.descent);
1588 //DBG_OBJ_ARRSET_NUM (page, "words.%d.size.ascent", page->num_words - 1,
1636 //DBG_OBJ_ARRSET_NUM (this, "words.%d.size.ascent", words->size() - 1,
15891637 // word->size.ascent);
1590 //DBG_OBJ_ARRSET_NUM (page, "words.%d.orig_space", page->num_words - 1,
1638 //DBG_OBJ_ARRSET_NUM (this, "words.%d.orig_space", words->size() - 1,
15911639 // word->orig_space);
1592 //DBG_OBJ_ARRSET_NUM (page, "words.%d.eff_space", page->num_words - 1,
1640 //DBG_OBJ_ARRSET_NUM (this, "words.%d.effSpace", words->size() - 1,
15931641 // word->eff_space);
1594 //DBG_OBJ_ARRSET_NUM (page, "words.%d.content.space", page->num_words - 1,
1642 //DBG_OBJ_ARRSET_NUM (this, "words.%d.content.space", words->size() - 1,
15951643 // word->content.space);
15961644
15971645 word->style = style;
16021650 return word;
16031651 }
16041652
1653 /*
1654 * Get the width of a string of text.
1655 */
1656 int Textblock::textWidth(const char *text, int start, int len,
1657 core::style::Style *style)
1658 {
1659 int ret = 0;
1660
1661 if (len > 0) {
1662 char *str = NULL;
1663
1664 switch (style->textTransform) {
1665 case core::style::TEXT_TRANSFORM_NONE:
1666 default:
1667 ret = layout->textWidth(style->font, text+start, len);
1668 break;
1669 case core::style::TEXT_TRANSFORM_UPPERCASE:
1670 str = layout->textToUpper(text+start, len);
1671 ret = layout->textWidth(style->font, str, strlen(str));
1672 break;
1673 case core::style::TEXT_TRANSFORM_LOWERCASE:
1674 str = layout->textToLower(text+start, len);
1675 ret = layout->textWidth(style->font, str, strlen(str));
1676 break;
1677 case core::style::TEXT_TRANSFORM_CAPITALIZE:
1678 {
1679 /* \bug No way to know about non-ASCII punctuation. */
1680 bool initial_seen = false;
1681
1682 for (int i = 0; i < start; i++)
1683 if (!ispunct(text[i]))
1684 initial_seen = true;
1685 if (initial_seen) {
1686 ret = layout->textWidth(style->font, text+start, len);
1687 } else {
1688 int after = 0;
1689
1690 text += start;
1691 while (ispunct(text[after]))
1692 after++;
1693 if (text[after])
1694 after = layout->nextGlyph(text, after);
1695 if (after > len)
1696 after = len;
1697 str = layout->textToUpper(text, after);
1698 ret = layout->textWidth(style->font, str, strlen(str)) +
1699 layout->textWidth(style->font, text+after, len-after);
1700 }
1701 break;
1702 }
1703 }
1704 if (str)
1705 free(str);
1706 }
1707 return ret;
1708 }
1709
16051710 /**
16061711 * Calculate the size of a text word.
16071712 */
16091714 core::style::Style *style,
16101715 core::Requisition *size)
16111716 {
1612 size->width = layout->textWidth (style->font, text, len);
1717 size->width = textWidth (text, 0, len, style);
16131718 size->ascent = style->font->ascent;
16141719 size->descent = style->font->descent;
16151720
16681773 word->content.type = core::Content::TEXT;
16691774 word->content.text = layout->textZone->strndup(text, len);
16701775
1671 //DBG_OBJ_ARRSET_STR (page, "words.%d.content.text", page->num_words - 1,
1776 //DBG_OBJ_ARRSET_STR (page, "words.%d.content.text", words->size() - 1,
16721777 // word->content.text);
16731778
16741779 wordWrap (words->size () - 1);
16971802 word->content.type = core::Content::WIDGET;
16981803 word->content.widget = widget;
16991804
1700 //DBG_OBJ_ARRSET_PTR (page, "words.%d.content.widget", page->num_words - 1,
1805 //DBG_OBJ_ARRSET_PTR (page, "words.%d.content.widget", words->size() - 1,
17011806 // word->content.widget);
17021807
17031808 wordWrap (words->size () - 1);
17081813 //DEBUG_MSG(DEBUG_REWRAP_LEVEL,
17091814 // "Assigning parent_ref = %d to added word %d, "
17101815 // "in page with %d word(s)\n",
1711 // page->num_lines - 1, page->num_words - 1, page->num_words);
1712 }
1713
1816 // lines->size () - 1, words->size() - 1, words->size());
1817 }
17141818
17151819 /**
17161820 * Add an anchor to the page. "name" is copied, so no strdup is necessary for
17631867 if (wordIndex >= 0) {
17641868 Word *word = words->getRef(wordIndex);
17651869
1870 // According to http://www.w3.org/TR/CSS2/text.html#white-space-model:
1871 // "line breaking opportunities are determined based on the text prior
1872 // to the white space collapsing steps".
1873 // So we call addBreakOption () for each Textblock::addSpace () call.
1874 // This is important e.g. to be able to break between foo and bar in:
1875 // <span style="white-space:nowrap">foo </span> bar
1876 addBreakOption (style);
1877
17661878 if (!word->content.space) {
17671879 word->content.space = true;
17681880 word->effSpace = word->origSpace = style->font->spaceWidth +
17691881 style->wordSpacing;
17701882
1771 //DBG_OBJ_ARRSET_NUM (page, "words.%d.orig_space", nw,
1772 // page->words[nw].orig_space);
1773 //DBG_OBJ_ARRSET_NUM (page, "words.%d.eff_space", nw,
1774 // page->words[nw].eff_space);
1775 //DBG_OBJ_ARRSET_NUM (page, "words.%d.content.space", nw,
1776 // page->words[nw].content.space);
1883 //DBG_OBJ_ARRSET_NUM (this, "words.%d.origSpace", wordIndex,
1884 // word->origSpace);
1885 //DBG_OBJ_ARRSET_NUM (this, "words.%d.effSpace", wordIndex,
1886 // word->effSpace);
1887 //DBG_OBJ_ARRSET_NUM (this, "words.%d.content.space", wordIndex,
1888 // word->content.space);
17771889 word->spaceStyle->unref ();
17781890 word->spaceStyle = style;
17791891 style->ref ();
17801892 }
17811893 }
17821894 }
1783
17841895
17851896 /**
17861897 * Cause a paragraph break
19412052 }
19422053
19432054 /*
1944 * Any words added by a_Dw_page_add_... are not immediately (queued to
2055 * Any words added by addWord() are not immediately (queued to
19452056 * be) drawn, instead, this function must be called. This saves some
1946 * calls to p_Dw_widget_queue_resize.
2057 * calls to queueResize().
19472058 *
19482059 */
19492060 void Textblock::flush ()
21842295 allocation->x += w->size.width + w->effSpace;
21852296 }
21862297 if (start > 0 && word->content.type == core::Content::TEXT) {
2187 allocation->x += textblock->layout->textWidth (word->style->font,
2188 word->content.text,
2189 start);
2298 allocation->x += textblock->textWidth (word->content.text, 0, start,
2299 word->style);
21902300 }
21912301 allocation->y = textblock->lineYOffsetCanvas (line) + line->boxAscent -
21922302 word->size.ascent;
21982308 if (start > 0 || end < wordEnd) {
21992309 end = misc::min(end, wordEnd); /* end could be INT_MAX */
22002310 allocation->width =
2201 textblock->layout->textWidth (word->style->font,
2202 word->content.text + start,
2203 end - start);
2311 textblock->textWidth (word->content.text, start, end - start,
2312 word->style);
22042313 }
22052314 }
22062315 allocation->ascent = word->size.ascent;
147147 /* The following members contain accumulated values, from the top
148148 * down to the line before. */
149149 int maxLineWidth; /* maximum of all line widths */
150 int maxWordMin; /* maximum of all word minima */
150 int maxParMin; /* maximum of all paragraph minima */
151151 int maxParMax; /* maximum of all paragraph maxima */
152 int parMin; /* the minimal total width down from the last
153 * paragraph start, to the *beginning* of the
154 * line */
155152 int parMax; /* the maximal total width down from the last
156153 * paragraph start, to the *beginning* of the
157154 * line */
239236 int availWidth, availAscent, availDescent;
240237
241238 int lastLineWidth;
242 int lastLineParMin;
239 int lastLineParMin; /* width of the current non-breakable word sequence
240 * used by wordWrap () */
243241 int lastLineParMax;
244242 int wrapRef; /* [0 based] */
245243
255253
256254 void queueDrawRange (int index1, int index2);
257255 void getWordExtremes (Word *word, core::Extremes *extremes);
256 inline bool canBreakAfter (Word *word)
257 {
258 return word->content.breakType == core::Content::BREAK_OK;
259 }
258260 void markChange (int ref);
259261 void justifyLine (Line *line, int availWidth);
260262 Line *addLine (int wordInd, bool newPar);
263265 void decorateText(core::View *view, core::style::Style *style,
264266 core::style::Color::Shading shading,
265267 int x, int yBase, int width);
266 void drawText(int wordIndex, core::View *view, core::Rectangle *area,
268 void drawText(core::View *view, core::style::Style *style,
269 core::style::Color::Shading shading, int x, int y,
270 const char *text, int start, int len);
271 void drawWord(int wordIndex, core::View *view, core::Rectangle *area,
267272 int xWidget, int yWidgetBase);
268273 void drawSpace(int wordIndex, core::View *view, core::Rectangle *area,
269274 int xWidget, int yWidgetBase);
274279
275280 Word *addWord (int width, int ascent, int descent,
276281 core::style::Style *style);
282 int textWidth (const char *text, int start, int len,
283 core::style::Style *style);
277284 void calcTextSize (const char *text, size_t len, core::style::Style *style,
278285 core::Requisition *size);
279
280286
281287 /**
282288 * \brief Returns the x offset (the indentation plus any offset needed for
381387 void addWidget (core::Widget *widget, core::style::Style *style);
382388 bool addAnchor (const char *name, core::style::Style *style);
383389 void addSpace(core::style::Style *style);
390 inline void addBreakOption (core::style::Style *style)
391 {
392 int wordIndex = words->size () - 1;
393 if (wordIndex >= 0 &&
394 style->whiteSpace != core::style::WHITE_SPACE_NOWRAP &&
395 style->whiteSpace != core::style::WHITE_SPACE_PRE)
396 words->getRef(wordIndex)->content.breakType = core::Content::BREAK_OK;
397 }
384398 void addParbreak (int space, core::style::Style *style);
385399 void addLinebreak (core::style::Style *style);
386400
193193 REAL_CONTENT = 0xff ^ (START | END),
194194 SELECTION_CONTENT = TEXT | WIDGET | BREAK
195195 };
196 enum BreakType {
197 BREAK_NO,
198 BREAK_OK
199 };
196200 /* Content is embedded in struct Word therefore we
197201 * try to be space efficient.
198202 */
199203 short type;
200204 bool space;
205 unsigned char breakType;
201206 union {
202207 const char *text;
203208 Widget *widget;
00 #!/bin/sh
1 #
2 # $NetBSD: install-sh.in,v 1.5 2010/10/08 19:57:05 tez Exp $
3 # This script now also installs multiple files, but might choke on installing
4 # multiple files with spaces in the file names.
5 #
61 # install - install a program, script, or datafile
7 # This comes from X11R5 (mit/util/scripts/install.sh).
8 #
9 # Copyright 1991 by the Massachusetts Institute of Technology
10 #
11 # Permission to use, copy, modify, distribute, and sell this software and its
12 # documentation for any purpose is hereby granted without fee, provided that
13 # the above copyright notice appear in all copies and that both that
14 # copyright notice and this permission notice appear in supporting
15 # documentation, and that the name of M.I.T. not be used in advertising or
16 # publicity pertaining to distribution of the software without specific,
17 # written prior permission. M.I.T. makes no representations about the
18 # suitability of this software for any purpose. It is provided "as is"
19 # without express or implied warranty.
2
3 scriptversion=2009-04-28.21; # UTC
4
5 # This originates from X11R5 (mit/util/scripts/install.sh), which was
6 # later released in X11R6 (xc/config/util/install.sh) with the
7 # following copyright and license.
8 #
9 # Copyright (C) 1994 X Consortium
10 #
11 # Permission is hereby granted, free of charge, to any person obtaining a copy
12 # of this software and associated documentation files (the "Software"), to
13 # deal in the Software without restriction, including without limitation the
14 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
15 # sell copies of the Software, and to permit persons to whom the Software is
16 # furnished to do so, subject to the following conditions:
17 #
18 # The above copyright notice and this permission notice shall be included in
19 # all copies or substantial portions of the Software.
20 #
21 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
25 # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
26 # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #
28 # Except as contained in this notice, the name of the X Consortium shall not
29 # be used in advertising or otherwise to promote the sale, use or other deal-
30 # ings in this Software without prior written authorization from the X Consor-
31 # tium.
32 #
33 #
34 # FSF changes to this file are in the public domain.
2035 #
2136 # Calling this script install-sh is preferred over install.sh, to prevent
2237 # `make' implicit rules from creating a file called install from it
2540 # This script is compatible with the BSD install script, but was written
2641 # from scratch.
2742
43 nl='
44 '
45 IFS=" "" $nl"
46
2847 # set DOITPROG to echo to test this script
2948
3049 # Don't use :- since 4.3BSD and earlier shells don't like it.
31 doit="${DOITPROG-}"
32
33
34 # put in absolute paths if you don't have them in your path; or use env. vars.
35
36 awkprog="${AWKPROG-awk}"
37 mvprog="${MVPROG-mv}"
38 cpprog="${CPPROG-cp}"
39 chmodprog="${CHMODPROG-chmod}"
40 chownprog="${CHOWNPROG-chown}"
41 chgrpprog="${CHGRPPROG-chgrp}"
42 stripprog="${STRIPPROG-strip}"
43 rmprog="${RMPROG-rm}"
44 mkdirprog="${MKDIRPROG-mkdir}"
45
46 instcmd="$cpprog"
47 pathcompchmodcmd="$chmodprog 755"
48 chmodcmd="$chmodprog 755"
49 chowncmd=""
50 chgrpcmd=""
51 stripcmd=""
52 stripflags=""
50 doit=${DOITPROG-}
51 if test -z "$doit"; then
52 doit_exec=exec
53 else
54 doit_exec=$doit
55 fi
56
57 # Put in absolute file names if you don't have them in your path;
58 # or use environment vars.
59
60 chgrpprog=${CHGRPPROG-chgrp}
61 chmodprog=${CHMODPROG-chmod}
62 chownprog=${CHOWNPROG-chown}
63 cmpprog=${CMPPROG-cmp}
64 cpprog=${CPPROG-cp}
65 mkdirprog=${MKDIRPROG-mkdir}
66 mvprog=${MVPROG-mv}
67 rmprog=${RMPROG-rm}
68 stripprog=${STRIPPROG-strip}
69
70 posix_glob='?'
71 initialize_posix_glob='
72 test "$posix_glob" != "?" || {
73 if (set -f) 2>/dev/null; then
74 posix_glob=
75 else
76 posix_glob=:
77 fi
78 }
79 '
80
81 posix_mkdir=
82
83 # Desired mode of installed file.
84 mode=0755
85
86 chgrpcmd=
87 chmodcmd=$chmodprog
88 chowncmd=
89 mvcmd=$mvprog
5390 rmcmd="$rmprog -f"
54 mvcmd="$mvprog"
55 src=""
56 msrc=""
57 dst=""
58 dir_arg=""
59 suffix=""
60 suffixfmt=""
61
62 while [ x"$1" != x ]; do
63 case $1 in
64 -b) suffix=".old"
65 shift
66 continue;;
67
68 -B) suffixfmt="$2"
69 shift
70 shift
71 continue;;
72
73 -c) instcmd="$cpprog"
74 shift
75 continue;;
76
77 -d) dir_arg=true
78 shift
79 continue;;
80
81 -m) chmodcmd="$chmodprog $2"
82 shift
83 shift
84 continue;;
85
86 -o) chowncmd="$chownprog $2"
87 shift
88 shift
89 continue;;
90
91 -g) chgrpcmd="$chgrpprog $2"
92 shift
93 shift
94 continue;;
95
96 -s) stripcmd="$stripprog"
97 shift
98 continue;;
99
100 -S) stripcmd="$stripprog"
101 stripflags="-S $2 $stripflags"
102 shift
103 shift
104 continue;;
105
106 *) if [ x"$msrc" = x ]
91 stripcmd=
92
93 src=
94 dst=
95 dir_arg=
96 dst_arg=
97
98 copy_on_change=false
99 no_target_directory=
100
101 usage="\
102 Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
103 or: $0 [OPTION]... SRCFILES... DIRECTORY
104 or: $0 [OPTION]... -t DIRECTORY SRCFILES...
105 or: $0 [OPTION]... -d DIRECTORIES...
106
107 In the 1st form, copy SRCFILE to DSTFILE.
108 In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
109 In the 4th, create DIRECTORIES.
110
111 Options:
112 --help display this help and exit.
113 --version display version info and exit.
114
115 -c (ignored)
116 -C install only if different (preserve the last data modification time)
117 -d create directories instead of installing files.
118 -g GROUP $chgrpprog installed files to GROUP.
119 -m MODE $chmodprog installed files to MODE.
120 -o USER $chownprog installed files to USER.
121 -s $stripprog installed files.
122 -t DIRECTORY install into DIRECTORY.
123 -T report an error if DSTFILE is a directory.
124
125 Environment variables override the default commands:
126 CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
127 RMPROG STRIPPROG
128 "
129
130 while test $# -ne 0; do
131 case $1 in
132 -c) ;;
133
134 -C) copy_on_change=true;;
135
136 -d) dir_arg=true;;
137
138 -g) chgrpcmd="$chgrpprog $2"
139 shift;;
140
141 --help) echo "$usage"; exit $?;;
142
143 -m) mode=$2
144 case $mode in
145 *' '* | *' '* | *'
146 '* | *'*'* | *'?'* | *'['*)
147 echo "$0: invalid mode: $mode" >&2
148 exit 1;;
149 esac
150 shift;;
151
152 -o) chowncmd="$chownprog $2"
153 shift;;
154
155 -s) stripcmd=$stripprog;;
156
157 -t) dst_arg=$2
158 shift;;
159
160 -T) no_target_directory=true;;
161
162 --version) echo "$0 $scriptversion"; exit $?;;
163
164 --) shift
165 break;;
166
167 -*) echo "$0: invalid option: $1" >&2
168 exit 1;;
169
170 *) break;;
171 esac
172 shift
173 done
174
175 if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
176 # When -d is used, all remaining arguments are directories to create.
177 # When -t is used, the destination is already specified.
178 # Otherwise, the last argument is the destination. Remove it from $@.
179 for arg
180 do
181 if test -n "$dst_arg"; then
182 # $@ is not empty: it contains at least $arg.
183 set fnord "$@" "$dst_arg"
184 shift # fnord
185 fi
186 shift # arg
187 dst_arg=$arg
188 done
189 fi
190
191 if test $# -eq 0; then
192 if test -z "$dir_arg"; then
193 echo "$0: no input file specified." >&2
194 exit 1
195 fi
196 # It's OK to call `install-sh -d' without argument.
197 # This can happen when creating conditional directories.
198 exit 0
199 fi
200
201 if test -z "$dir_arg"; then
202 trap '(exit $?); exit' 1 2 13 15
203
204 # Set umask so as not to create temps with too-generous modes.
205 # However, 'strip' requires both read and write access to temps.
206 case $mode in
207 # Optimize common cases.
208 *644) cp_umask=133;;
209 *755) cp_umask=22;;
210
211 *[0-7])
212 if test -z "$stripcmd"; then
213 u_plus_rw=
214 else
215 u_plus_rw='% 200'
216 fi
217 cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
218 *)
219 if test -z "$stripcmd"; then
220 u_plus_rw=
221 else
222 u_plus_rw=,u+rw
223 fi
224 cp_umask=$mode$u_plus_rw;;
225 esac
226 fi
227
228 for src
229 do
230 # Protect names starting with `-'.
231 case $src in
232 -*) src=./$src;;
233 esac
234
235 if test -n "$dir_arg"; then
236 dst=$src
237 dstdir=$dst
238 test -d "$dstdir"
239 dstdir_status=$?
240 else
241
242 # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
243 # might cause directories to be created, which would be especially bad
244 # if $src (and thus $dsttmp) contains '*'.
245 if test ! -f "$src" && test ! -d "$src"; then
246 echo "$0: $src does not exist." >&2
247 exit 1
248 fi
249
250 if test -z "$dst_arg"; then
251 echo "$0: no destination specified." >&2
252 exit 1
253 fi
254
255 dst=$dst_arg
256 # Protect names starting with `-'.
257 case $dst in
258 -*) dst=./$dst;;
259 esac
260
261 # If destination is a directory, append the input filename; won't work
262 # if double slashes aren't ignored.
263 if test -d "$dst"; then
264 if test -n "$no_target_directory"; then
265 echo "$0: $dst_arg: Is a directory" >&2
266 exit 1
267 fi
268 dstdir=$dst
269 dst=$dstdir/`basename "$src"`
270 dstdir_status=0
271 else
272 # Prefer dirname, but fall back on a substitute if dirname fails.
273 dstdir=`
274 (dirname "$dst") 2>/dev/null ||
275 expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
276 X"$dst" : 'X\(//\)[^/]' \| \
277 X"$dst" : 'X\(//\)$' \| \
278 X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
279 echo X"$dst" |
280 sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
281 s//\1/
282 q
283 }
284 /^X\(\/\/\)[^/].*/{
285 s//\1/
286 q
287 }
288 /^X\(\/\/\)$/{
289 s//\1/
290 q
291 }
292 /^X\(\/\).*/{
293 s//\1/
294 q
295 }
296 s/.*/./; q'
297 `
298
299 test -d "$dstdir"
300 dstdir_status=$?
301 fi
302 fi
303
304 obsolete_mkdir_used=false
305
306 if test $dstdir_status != 0; then
307 case $posix_mkdir in
308 '')
309 # Create intermediate dirs using mode 755 as modified by the umask.
310 # This is like FreeBSD 'install' as of 1997-10-28.
311 umask=`umask`
312 case $stripcmd.$umask in
313 # Optimize common cases.
314 *[2367][2367]) mkdir_umask=$umask;;
315 .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
316
317 *[0-7])
318 mkdir_umask=`expr $umask + 22 \
319 - $umask % 100 % 40 + $umask % 20 \
320 - $umask % 10 % 4 + $umask % 2
321 `;;
322 *) mkdir_umask=$umask,go-w;;
323 esac
324
325 # With -d, create the new directory with the user-specified mode.
326 # Otherwise, rely on $mkdir_umask.
327 if test -n "$dir_arg"; then
328 mkdir_mode=-m$mode
329 else
330 mkdir_mode=
331 fi
332
333 posix_mkdir=false
334 case $umask in
335 *[123567][0-7][0-7])
336 # POSIX mkdir -p sets u+wx bits regardless of umask, which
337 # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
338 ;;
339 *)
340 tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
341 trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
342
343 if (umask $mkdir_umask &&
344 exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
107345 then
108 msrc="$dst"
346 if test -z "$dir_arg" || {
347 # Check for POSIX incompatibilities with -m.
348 # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
349 # other-writeable bit of parent directory when it shouldn't.
350 # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
351 ls_ld_tmpdir=`ls -ld "$tmpdir"`
352 case $ls_ld_tmpdir in
353 d????-?r-*) different_mode=700;;
354 d????-?--*) different_mode=755;;
355 *) false;;
356 esac &&
357 $mkdirprog -m$different_mode -p -- "$tmpdir" && {
358 ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
359 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
360 }
361 }
362 then posix_mkdir=:
363 fi
364 rmdir "$tmpdir/d" "$tmpdir"
109365 else
110 msrc="$msrc $dst"
366 # Remove any dirs left behind by ancient mkdir implementations.
367 rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
111368 fi
112 src="$dst"
113 dst="$1"
114 shift
115 continue;;
369 trap '' 0;;
370 esac;;
116371 esac
372
373 if
374 $posix_mkdir && (
375 umask $mkdir_umask &&
376 $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
377 )
378 then :
379 else
380
381 # The umask is ridiculous, or mkdir does not conform to POSIX,
382 # or it failed possibly due to a race condition. Create the
383 # directory the slow way, step by step, checking for races as we go.
384
385 case $dstdir in
386 /*) prefix='/';;
387 -*) prefix='./';;
388 *) prefix='';;
389 esac
390
391 eval "$initialize_posix_glob"
392
393 oIFS=$IFS
394 IFS=/
395 $posix_glob set -f
396 set fnord $dstdir
397 shift
398 $posix_glob set +f
399 IFS=$oIFS
400
401 prefixes=
402
403 for d
404 do
405 test -z "$d" && continue
406
407 prefix=$prefix$d
408 if test -d "$prefix"; then
409 prefixes=
410 else
411 if $posix_mkdir; then
412 (umask=$mkdir_umask &&
413 $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
414 # Don't fail if two instances are running concurrently.
415 test -d "$prefix" || exit 1
416 else
417 case $prefix in
418 *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
419 *) qprefix=$prefix;;
420 esac
421 prefixes="$prefixes '$qprefix'"
422 fi
423 fi
424 prefix=$prefix/
425 done
426
427 if test -n "$prefixes"; then
428 # Don't fail if two instances are running concurrently.
429 (umask $mkdir_umask &&
430 eval "\$doit_exec \$mkdirprog $prefixes") ||
431 test -d "$dstdir" || exit 1
432 obsolete_mkdir_used=true
433 fi
434 fi
435 fi
436
437 if test -n "$dir_arg"; then
438 { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
439 { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
440 { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
441 test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
442 else
443
444 # Make a couple of temp file names in the proper directory.
445 dsttmp=$dstdir/_inst.$$_
446 rmtmp=$dstdir/_rm.$$_
447
448 # Trap to clean up those temp files at exit.
449 trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
450
451 # Copy the file name to the temp name.
452 (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
453
454 # and set any options; do chmod last to preserve setuid bits.
455 #
456 # If any of these fail, we abort the whole thing. If we want to
457 # ignore errors from any of these, just make sure not to ignore
458 # errors from the above "$doit $cpprog $src $dsttmp" command.
459 #
460 { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
461 { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
462 { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
463 { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
464
465 # If -C, don't bother to copy if it wouldn't change the file.
466 if $copy_on_change &&
467 old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
468 new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
469
470 eval "$initialize_posix_glob" &&
471 $posix_glob set -f &&
472 set X $old && old=:$2:$4:$5:$6 &&
473 set X $new && new=:$2:$4:$5:$6 &&
474 $posix_glob set +f &&
475
476 test "$old" = "$new" &&
477 $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
478 then
479 rm -f "$dsttmp"
480 else
481 # Rename the file to the real destination.
482 $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
483
484 # The rename failed, perhaps because mv can't rename something else
485 # to itself, or perhaps because mv is so ancient that it does not
486 # support -f.
487 {
488 # Now remove or move aside any old file at destination location.
489 # We try this two ways since rm can't unlink itself on some
490 # systems and the destination file might be busy for other
491 # reasons. In this case, the final cleanup might fail but the new
492 # file should still install successfully.
493 {
494 test ! -f "$dst" ||
495 $doit $rmcmd -f "$dst" 2>/dev/null ||
496 { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
497 { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
498 } ||
499 { echo "$0: cannot unlink or rename $dst" >&2
500 (exit 1); exit 1
501 }
502 } &&
503
504 # Now rename the file to the real destination.
505 $doit $mvcmd "$dsttmp" "$dst"
506 }
507 fi || exit 1
508
509 trap '' 0
510 fi
117511 done
118512
119 if [ x"$dir_arg" = x ]
120 then
121 dstisfile=""
122 if [ ! -d "$dst" ]
123 then
124 if [ x"$msrc" = x"$src" ]
125 then
126 dstisfile=true
127 else
128 echo "install: destination is not a directory"
129 exit 1
130 fi
131 fi
132 else
133 msrc="$msrc $dst"
134 fi
135
136 if [ x"$msrc" = x ]
137 then
138 echo "install: no destination specified"
139 exit 1
140 fi
141
142 for srcarg in $msrc; do
143
144 if [ x"$dir_arg" != x ]; then
145
146 dstarg="$srcarg"
147 else
148 dstarg="$dst"
149
150 # Waiting for this to be detected by the "$instcmd $srcarg $dsttmp" command
151 # might cause directories to be created, which would be especially bad
152 # if $src (and thus $dsttmp) contains '*'.
153
154 if [ -f "$srcarg" ]
155 then
156 doinst="$instcmd"
157 elif [ -d "$srcarg" ]
158 then
159 echo "install: $srcarg: not a regular file"
160 exit 1
161 elif [ "$srcarg" = "/dev/null" ]
162 then
163 doinst="$cpprog"
164 else
165 echo "install: $srcarg does not exist"
166 exit 1
167 fi
168
169 # If destination is a directory, append the input filename; if your system
170 # does not like double slashes in filenames, you may need to add some logic
171
172 if [ -d "$dstarg" ]
173 then
174 dstarg="$dstarg"/`basename "$srcarg"`
175 fi
176 fi
177
178 ## this sed command emulates the dirname command
179 dstdir=`echo "$dstarg" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
180
181 # Make sure that the destination directory exists.
182 # this part is taken from Noah Friedman's mkinstalldirs script
183
184 # Skip lots of stat calls in the usual case.
185 if [ ! -d "$dstdir" ]; then
186 defaultIFS='
187 '
188 IFS="${IFS-${defaultIFS}}"
189
190 oIFS="${IFS}"
191 # Some sh's can't handle IFS=/ for some reason.
192 IFS='%'
193 set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
194 IFS="${oIFS}"
195
196 pathcomp=''
197
198 while [ $# -ne 0 ] ; do
199 pathcomp="${pathcomp}${1}"
200 shift
201
202 if [ ! -d "${pathcomp}" ] ;
203 then
204 $doit $mkdirprog "${pathcomp}"
205 if [ x"$chowncmd" != x ]; then $doit $chowncmd "${pathcomp}"; else true ; fi &&
206 if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "${pathcomp}"; else true ; fi &&
207 if [ x"$pathcompchmodcmd" != x ]; then $doit $pathcompchmodcmd "${pathcomp}"; else true ; fi
208
209 else
210 true
211 fi
212
213 pathcomp="${pathcomp}/"
214 done
215 fi
216
217 if [ x"$dir_arg" != x ]
218 then
219 if [ -d "$dstarg" ]; then
220 true
221 else
222 $doit $mkdirprog "$dstarg" &&
223
224 if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dstarg"; else true ; fi &&
225 if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dstarg"; else true ; fi &&
226 if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dstarg"; else true ; fi
227 fi
228 else
229
230 if [ x"$dstisfile" = x ]
231 then
232 file=$srcarg
233 else
234 file=$dst
235 fi
236
237 dstfile=`basename "$file"`
238 dstfinal="$dstdir/$dstfile"
239
240 # Make a temp file name in the proper directory.
241
242 dsttmp=$dstdir/#inst.$$#
243
244 # Make a backup file name in the proper directory.
245 case x$suffixfmt in
246 *%*) suffix=`echo x |
247 $awkprog -v bname="$dstfinal" -v fmt="$suffixfmt" '
248 { cnt = 0;
249 do {
250 sfx = sprintf(fmt, cnt++);
251 name = bname sfx;
252 } while (system("test -f " name) == 0);
253 print sfx; }' -`;;
254 x) ;;
255 *) suffix="$suffixfmt";;
256 esac
257 dstbackup="$dstfinal$suffix"
258
259 # Move or copy the file name to the temp name
260
261 $doit $doinst $srcarg "$dsttmp" &&
262
263 trap "rm -f ${dsttmp}" 0 &&
264
265 # and set any options; do chmod last to preserve setuid bits
266
267 # If any of these fail, we abort the whole thing. If we want to
268 # ignore errors from any of these, just make sure not to ignore
269 # errors from the above "$doit $instcmd $src $dsttmp" command.
270
271 if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else true;fi &&
272 if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else true;fi &&
273 if [ x"$stripcmd" != x ]; then $doit $stripcmd $stripflags "$dsttmp"; else true;fi &&
274 if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else true;fi &&
275
276 # Now rename the file to the real destination.
277
278 if [ x"$suffix" != x ] && [ -f "$dstfinal" ]
279 then
280 $doit $mvcmd "$dstfinal" "$dstbackup"
281 else
282 $doit $rmcmd -f "$dstfinal"
283 fi &&
284 $doit $mvcmd "$dsttmp" "$dstfinal"
285 fi
286
287 done &&
288
289
290 exit 0
513 # Local variables:
514 # eval: (add-hook 'write-file-hooks 'time-stamp)
515 # time-stamp-start: "scriptversion="
516 # time-stamp-format: "%:y-%02m-%02d.%02H"
517 # time-stamp-time-zone: "UTC"
518 # time-stamp-end: "; # UTC"
519 # End:
66 * \brief This namespace contains a framework for container classes, which
77 * members are instances of object::Object.
88 *
9 * A common problem in languanges without garbage collection is, where the
9 * A common problem in languages without garbage collection is, where the
1010 * children belong to, and so, who is responsible to delete them (instantiation
1111 * is always done by the caller). This information is here told to the
1212 * collections, each container has a constructor with the parameter
4040 inline int roundInt(double d)
4141 {
4242 return (int) ((d > 0) ? (d + 0.5) : (d - 0.5));
43 }
44
45 inline int AsciiTolower(char c)
46 {
47 return ((c >= 'A' && c <= 'Z') ? c + 0x20 : c);
48 }
49
50 inline int AsciiToupper(char c)
51 {
52 return ((c >= 'a' && c <= 'z') ? c - 0x20 : c);
53 }
54
55 inline int AsciiStrcasecmp(const char *s1, const char *s2)
56 {
57 int ret = 0;
58
59 while ((*s1 || *s2) && !(ret = AsciiTolower(*s1) - AsciiTolower(*s2))) {
60 s1++;
61 s2++;
62 }
63 return ret;
4364 }
4465
4566 /**
155155 " <td><a href='http://www.gutenberg.org/'>P.&nbsp;Gutenberg</a>\n"
156156 " <tr>\n"
157157 " <td>&nbsp;&nbsp;\n"
158 " <td><a href='http://freshmeat.net/'>FreshMeat</a>\n"
158 " <td><a href='http://freecode.com/'>Freecode</a>\n"
159159 " <tr>\n"
160160 " <td>&nbsp;&nbsp;\n"
161161 " <td><a href='http://www.gnu.org/gnu/thegnuproject.html'>GNU\n"
210210 " <td bgcolor='#FFFFFF'>\n"
211211 " <table border='0' cellspacing='0' cellpadding='5'><tr><td>\n"
212212 " <p>\n"
213 " Dillo is Free Software under the terms of version 3 of the\n"
214 " <a href='http://www.gnu.org/licenses/gpl.html'>GPL</a>.\n"
213 " The Dillo web browser is Free Software under the terms of version 3 of\n"
214 " the <a href='http://www.gnu.org/licenses/gpl.html'>GPL</a>.\n"
215215 " This means you have four basic freedoms:\n"
216216 " <ul>\n"
217217 " <li>Freedom to use the program any way you see fit.\n"
233233 "<tr>\n"
234234 " <td bgcolor='#CCCCCC'>\n"
235235 " <h4>Release overview</h4>\n"
236 " September 21, 2011\n"
236 " December 05, 2011\n"
237237 "<tr>\n"
238238 " <td bgcolor='#FFFFFF'>\n"
239239 " <table border='0' cellspacing='0' cellpadding='5'>\n"
240240 " <tr>\n"
241241 " <td>\n"
242242 "<p>\n"
243 "The dillo-3.0.1 release brings improved privacy and some new options for\n"
244 "configuring the user interface.\n"
245 "<p>\n"
246 "Dillo3 is a port to FLTK-1.3, which is big news because FLTK-1.3.0 was\n"
247 "<a href='http://fltk.org/articles.php?L1086'>released</a>\n"
248 "in June, clearing the way for Dillo to return to those distributions\n"
249 "which had excluded Dillo2 due to FLTK2 never being officially released.\n"
250 "<p>\n"
251 "After this release, the core team will focus on implementing the CSS\n"
243 "dillo-3.0.2 brings you some new bits and pieces, as listed below :)\n"
244 "<p>\n"
245 "After this release, the core team plans to focus on implementing the CSS\n"
252246 "feature of floating elements. This will <em>greatly</em> improve dillo's\n"
253247 "web page rendering since many sites have adopted floats instead of tables.\n"
254248 "<p>\n"
255 "The new dillo3 has shown excellent stability in our experience.\n"
249 "Dillo3 uses the FLTK GUI toolkit's 1.3.x series. In June, fltk-1.3.0 was\n"
250 "<a href='http://fltk.org/articles.php?L1086'>released</a>,\n"
251 "clearing the way for Dillo to return to those distributions\n"
252 "which had excluded Dillo2 due to FLTK2 never being officially released.\n"
253 "<p>\n"
256254 "The core team welcomes developers willing to join our workforce.\n"
257255 "<p>\n"
258256 " </table>\n"
274272 " <table border='0' cellspacing='0' cellpadding='5'>\n"
275273 " <tr>\n"
276274 " <td>\n"
277 "dillo-3.0.1:\n"
278275 "<ul>\n"
279 "<li>Privacy -- never send cookies when making third-party requests, and\n"
280 " never accept cookies in the responses to these requests.\n"
281 "<li>Add preference for UI theme.\n"
282 "<li>Allow key bindings for paging left/right.\n"
283 "<li>Add show_quit_dialog dillorc option.\n"
284 "</ul>\n"
285 "dillo-3.0:\n"
286 "<ul>\n"
287 "<li>Ported Dillo to FLTK-1.3.\n"
288 "<li>Native build on OSX.\n"
289 "<li>Default binding for close-all changed from Alt-q to Ctrl-q.\n"
290 "<li>Default binding for close-tab changed from Ctrl-q to Ctrl-w.\n"
291 "<li>Default binding for left-tab changed to Shift-Ctrl-Tab.\n"
292 "<li>Rewrote the User Interface: much simpler design and event handling.\n"
293 "<li>Added on-the-fly panel resize (tiny/small/medium and normal/small icons).\n"
294 "<li>'hide-panels' key action now hides the findbar if present,\n"
295 " and toggles display of the control panels otherwise.\n"
296 "<li>Allow multiple search engines to be set in dillorc, with a menu\n"
297 " in the web search dialog to select between them.\n"
298 "<li>Added an optional label to dillorc's search_url.\n"
299 " Format: \"[&lt;label&gt; ]&lt;url&gt;\"\n"
300 "<li>Add right_click_closes_tab preference (default is middle click).\n"
301 "<li>Allow binding to non-ASCII keys and multimedia keys.\n"
302 "<li>Avoid a certificate dialog storm on some HTTPS sites (BUG#868).\n"
303 "<li>Enable line wrapping for &lt;textarea&gt;. (BUG#903)\n"
304 "<li>Avoid double render after going Back or Forward\n"
305 " (it takes half the time now!)\n"
306 "<li>Implemented a custom tabs handler (to allow fine control of it).\n"
307 "<li>Rewrote dw's crossing-events dispatcher (avoids redundant events).\n"
308 "<li>Fixed a years old bug: stamped tooltips when scrolling with keyboard.\n"
309 "<li>Fixed a border case in URL resolver: empty path + {query|fragment}\n"
310 " (BUG#948)\n"
311 "<li>Cancel the expected URL after offering a download (BUG#982)\n"
312 "<li>Eliminated a pack of 22 compiler warnings (gcc-4.6.1 amd64)\n"
313 "<li>Removed 'large' option of panel_size preference.\n"
314 "<li>Removed --enable-ansi configure option.\n"
315 "<li>Limit saved cookie size.\n"
316 "<li>Wrap image alt text.\n"
317 "<li>Added support for CSS adjacent sibling selectors.\n"
318 "<li>Fix redraw loops and reenabled limit_text_width dillorc option.\n"
319 "<li>Collapse parent's and first child's top margin.\n"
276 "<li>Digest authentication.\n"
277 "<li>Rework line breaking and fix white-space:nowrap handling.\n"
278 "<li>text-transform property.\n"
279 "<li>Locale-independent ASCII character case handling (fixes Turkic locales).\n"
280 "<li>Bind Ctrl-{PageUp,PageDown} to tab-{previous,next}.\n"
320281 "</ul>\n"
321282 " </table>\n"
322283 "</table>\n"
337298 "<ul>\n"
338299 " <li> There's a\n"
339300 " <a href='http://www.dillo.org/dillorc'>dillorc</a>\n"
340 " (readable config) file within the tarball; It is well-commented\n"
301 " (readable config) file inside the tarball. It is well-commented\n"
341302 " and has plenty of options to customize dillo, so <STRONG>copy\n"
342303 " it</STRONG> to your <STRONG>~/.dillo/</STRONG> directory, and\n"
343304 " modify it to your taste.\n"
344305 " <li> Documentation for developers is in the <CODE>/doc</CODE>\n"
345 " dir within the tarball; you can find directions on everything\n"
306 " dir inside the tarball; you can find directions on everything\n"
346307 " else at the home page.\n"
347308 " <li> The right mouse button brings up a context-sensitive menu\n"
348309 " (available on pages, links, images, forms, the Back and Forward buttons,\n"
170170 } else if (a_Web_valid(sd->web)) {
171171 /* start connecting the socket */
172172 if (Http_connect_socket(sd->Info) < 0) {
173 ChainLink *Info = sd->Info;
173174 MSG_BW(sd->web, 1, "ERROR: %s", dStrerror(sd->Err));
174 a_Chain_bfcb(OpAbort, sd->Info, NULL, "Both");
175 dFree(sd->Info);
176 Http_socket_free(VOIDP2INT(sd->Info->LocalKey));
175 a_Chain_bfcb(OpAbort, Info, NULL, "Both");
176 Http_socket_free(VOIDP2INT(Info->LocalKey)); /* free sd */
177 dFree(Info);
177178 } else {
178179 sd->connected_to = hc->host;
179180 hc->active_connections++;
201202 Http_connect_queued_sockets(hc);
202203 if (hc->active_connections == 0)
203204 Http_host_connection_remove(hc);
204 }
205 }
205206 dFree(S);
206207 }
207208 }
273274 Dstr *a_Http_make_query_str(const DilloUrl *url, const DilloUrl *requester,
274275 bool_t use_proxy)
275276 {
276 const char *auth;
277 char *ptr, *cookies, *referer;
277 char *ptr, *cookies, *referer, *auth;
278278 Dstr *query = dStr_new(""),
279 *full_path = dStr_new(""),
279 *request_uri = dStr_new(""),
280280 *proxy_auth = dStr_new("");
281281
282282 if (use_proxy) {
283 dStr_sprintfa(full_path, "%s%s",
283 dStr_sprintfa(request_uri, "%s%s",
284284 URL_STR(url),
285285 (URL_PATH_(url) || URL_QUERY_(url)) ? "" : "/");
286 if ((ptr = strrchr(full_path->str, '#')))
287 dStr_truncate(full_path, ptr - full_path->str);
286 if ((ptr = strrchr(request_uri->str, '#')))
287 dStr_truncate(request_uri, ptr - request_uri->str);
288288 if (HTTP_Proxy_Auth_base64)
289289 dStr_sprintf(proxy_auth, "Proxy-Authorization: Basic %s\r\n",
290290 HTTP_Proxy_Auth_base64);
291291 } else {
292 dStr_sprintfa(full_path, "%s%s%s%s",
292 dStr_sprintfa(request_uri, "%s%s%s%s",
293293 URL_PATH(url),
294294 URL_QUERY_(url) ? "?" : "",
295295 URL_QUERY(url),
297297 }
298298
299299 cookies = a_Cookies_get_query(url, requester);
300 auth = a_Auth_get_auth_str(url);
300 auth = a_Auth_get_auth_str(url, request_uri->str);
301301 referer = Http_get_referer(url);
302302 if (URL_FLAGS(url) & URL_Post) {
303303 Dstr *content_type = Http_make_content_type(url);
318318 "Content-Type: %s\r\n"
319319 "%s" /* cookies */
320320 "\r\n",
321 full_path->str, HTTP_Language_hdr, auth ? auth : "",
321 request_uri->str, HTTP_Language_hdr, auth ? auth : "",
322322 URL_AUTHORITY(url), proxy_auth->str, referer, prefs.http_user_agent,
323323 (long)URL_DATA(url)->len, content_type->str,
324324 cookies);
341341 "User-Agent: %s\r\n"
342342 "%s" /* cookies */
343343 "\r\n",
344 full_path->str,
344 request_uri->str,
345345 (URL_FLAGS(url) & URL_E2EQuery) ?
346346 "Cache-Control: no-cache\r\nPragma: no-cache\r\n" : "",
347347 HTTP_Language_hdr, auth ? auth : "", URL_AUTHORITY(url),
349349 }
350350 dFree(referer);
351351 dFree(cookies);
352
353 dStr_free(full_path, TRUE);
352 dFree(auth);
353
354 dStr_free(request_uri, TRUE);
354355 dStr_free(proxy_auth, TRUE);
355356 _MSG("Query: {%s}\n", dStr_printable(query, 8192));
356357 return query;
478479 for (p = np; (tok = dStrsep(&p, " ")); ) {
479480 int start = host_len - strlen(tok);
480481
481 if (start >= 0 && dStrcasecmp(host + start, tok) == 0) {
482 if (start >= 0 && dStrAsciiCasecmp(host + start, tok) == 0) {
482483 /* no_proxy token is suffix of host string */
483484 ret = 0;
484485 break;
717718 for (i = 0; i < dList_length(host_connections); i++) {
718719 hc = (HostConnection_t*) dList_nth_data(host_connections, i);
719720
720 if (dStrcasecmp(host, hc->host) == 0)
721 if (dStrAsciiCasecmp(host, hc->host) == 0)
721722 return hc;
722723 }
723724
6666
6767 if (Size) {
6868 for ( i = 0; i < MimeMinItemsSize; ++i )
69 if (dStrncasecmp(Key, MimeMinItems[i].Name, Size) == 0)
69 if (dStrnAsciiCasecmp(Key, MimeMinItems[i].Name, Size) == 0)
7070 return MimeMinItems[i].Data;
7171 }
7272 return NULL;
8282
8383 if (Size) {
8484 for ( i = 0; i < MimeMajItemsSize; ++i )
85 if (dStrncasecmp(Key, MimeMajItems[i].Name, Size) == 0)
85 if (dStrnAsciiCasecmp(Key, MimeMajItems[i].Name, Size) == 0)
8686 return MimeMajItems[i].Data;
8787 }
8888 return NULL;
3434 cookies.h \
3535 auth.c \
3636 auth.h \
37 md5.c \
38 md5.h \
39 digest.c \
40 digest.h \
3741 colors.c \
3842 colors.h \
3943 binaryconst.h \
5050 PROGRAMS = $(bin_PROGRAMS)
5151 am_dillo_OBJECTS = dillo.$(OBJEXT) paths.$(OBJEXT) ui.$(OBJEXT) \
5252 uicmd.$(OBJEXT) bw.$(OBJEXT) cookies.$(OBJEXT) auth.$(OBJEXT) \
53 colors.$(OBJEXT) misc.$(OBJEXT) history.$(OBJEXT) \
54 prefs.$(OBJEXT) prefsparser.$(OBJEXT) keys.$(OBJEXT) \
55 url.$(OBJEXT) bitvec.$(OBJEXT) klist.$(OBJEXT) chain.$(OBJEXT) \
56 utf8.$(OBJEXT) timeout.$(OBJEXT) dialog.$(OBJEXT) \
57 web.$(OBJEXT) nav.$(OBJEXT) cache.$(OBJEXT) decode.$(OBJEXT) \
58 dicache.$(OBJEXT) capi.$(OBJEXT) css.$(OBJEXT) \
59 cssparser.$(OBJEXT) styleengine.$(OBJEXT) plain.$(OBJEXT) \
60 html.$(OBJEXT) form.$(OBJEXT) table.$(OBJEXT) \
53 md5.$(OBJEXT) digest.$(OBJEXT) colors.$(OBJEXT) misc.$(OBJEXT) \
54 history.$(OBJEXT) prefs.$(OBJEXT) prefsparser.$(OBJEXT) \
55 keys.$(OBJEXT) url.$(OBJEXT) bitvec.$(OBJEXT) klist.$(OBJEXT) \
56 chain.$(OBJEXT) utf8.$(OBJEXT) timeout.$(OBJEXT) \
57 dialog.$(OBJEXT) web.$(OBJEXT) nav.$(OBJEXT) cache.$(OBJEXT) \
58 decode.$(OBJEXT) dicache.$(OBJEXT) capi.$(OBJEXT) \
59 css.$(OBJEXT) cssparser.$(OBJEXT) styleengine.$(OBJEXT) \
60 plain.$(OBJEXT) html.$(OBJEXT) form.$(OBJEXT) table.$(OBJEXT) \
6161 bookmark.$(OBJEXT) dns.$(OBJEXT) gif.$(OBJEXT) jpeg.$(OBJEXT) \
6262 png.$(OBJEXT) imgbuf.$(OBJEXT) image.$(OBJEXT) menu.$(OBJEXT) \
6363 dpiapi.$(OBJEXT) findbar.$(OBJEXT) xembed.$(OBJEXT)
295295 cookies.h \
296296 auth.c \
297297 auth.h \
298 md5.c \
299 md5.h \
300 digest.c \
301 digest.h \
298302 colors.c \
299303 colors.h \
300304 binaryconst.h \
474478 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decode.Po@am__quote@
475479 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dialog.Po@am__quote@
476480 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dicache.Po@am__quote@
481 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/digest.Po@am__quote@
477482 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dillo.Po@am__quote@
478483 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dns.Po@am__quote@
479484 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dpiapi.Po@am__quote@
487492 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jpeg.Po@am__quote@
488493 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keys.Po@am__quote@
489494 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/klist.Po@am__quote@
495 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Po@am__quote@
490496 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/menu.Po@am__quote@
491497 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@
492498 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nav.Po@am__quote@
11 * File: auth.c
22 *
33 * Copyright 2008 Jeremy Henty <onepoint@starurchin.org>
4 * Copyright 2009 Justus Winter <4winter@informatik.uni-hamburg.de>
45 *
56 * This program is free software; you can redistribute it and/or modify
67 * it under the terms of the GNU General Public License as published by
1920 #include "msg.h"
2021 #include "misc.h"
2122 #include "dialog.hh"
23 #include "digest.h"
2224 #include "../dlib/dlib.h"
23
2425
2526 typedef struct {
2627 int ok;
28 enum AuthParseHTTPAuthType_t type;
2729 const char *realm;
30 const char *nonce;
31 const char *opaque;
32 int stale;
33 enum AuthParseDigestAlgorithm_t algorithm;
34 const char *domain;
35 enum AuthParseDigestQOP_t qop;
2836 } AuthParse_t;
29
30 typedef struct {
31 char *name;
32 Dlist *paths; /* stripped of any trailing '/', so the root path is "" */
33 char *authorization; /* the authorization request header */
34 } AuthRealm_t;
3537
3638 typedef struct {
3739 char *scheme;
4042 } AuthHost_t;
4143
4244 typedef struct {
43 const char *realm_name;
45 const AuthParse_t *auth_parse;
4446 const DilloUrl *url;
4547 } AuthDialogData_t;
4648
6163 {
6264 AuthParse_t *auth_parse = dNew(AuthParse_t, 1);
6365 auth_parse->ok = 0;
66 auth_parse->type = TYPENOTSET;
6467 auth_parse->realm = NULL;
68 auth_parse->nonce = NULL;
69 auth_parse->opaque = NULL;
70 auth_parse->stale = 0;
71 auth_parse->algorithm = ALGORITHMNOTSET;
72 auth_parse->domain = NULL;
73 auth_parse->qop = QOPNOTSET;
6574 return auth_parse;
6675 }
6776
6978 {
7079 if (auth_parse) {
7180 dFree((void *)auth_parse->realm);
81 dFree((void *)auth_parse->nonce);
82 dFree((void *)auth_parse->opaque);
83 dFree((void *)auth_parse->domain);
7284 dFree(auth_parse);
7385 }
7486 }
91103 static int Auth_is_token_char(char c)
92104 {
93105 const char *invalid = "\"()<>@,;:\\[]?=/{} \t";
94 return (strchr(invalid, c) || iscntrl((uchar_t)c)) ? 0 : 1;
95 }
96
97 /*
98 * Unquote the content of a quoted string.
106 return (!isascii(c) || strchr(invalid, c) || iscntrl((uchar_t)c)) ? 0 : 1;
107 }
108
109 /*
110 * Unquote the content of a (potentially) quoted string.
99111 * Return: newly allocated unquoted content.
100112 *
101113 * Arguments:
102 * quoted: pointer to the first char *after* the initial double quote.
103 * size: the number of chars in the result, *not* including a final '\0'.
114 * valuep: pointer to a pointer to the first char.
104115 *
105116 * Preconditions:
106 * quoted points to a correctly quoted and escaped string.
107 * size is the number of characters in the quoted string, *after*
108 * removing escape characters.
109 *
110 */
111 static const char *Auth_unquote_value(const char *quoted, int size)
112 {
113 char c, *value, *value_ptr;
114 value_ptr = value = dNew(char, size + 1);
115 while ((c = *quoted++) != '"')
116 *value_ptr++ = (c == '\\') ? *quoted++ : c;
117 *value_ptr = '\0';
118 return value;
119 }
120
121 /*
122 * Parse a quoted string. Save the result as the auth realm if required.
117 * *valuep points to a correctly quoted and escaped string.
118 *
119 * Postconditions:
120 * *valuep points to the first not processed char.
121 *
122 */
123 static Dstr *Auth_unquote_value(char **valuep)
124 {
125 char c, quoted;
126 char *value = *valuep;
127 Dstr *result;
128
129 while (*value == ' ' || *value == '\t')
130 value++;
131
132 if ((quoted = *value == '"'))
133 value++;
134
135 result = dStr_new(NULL);
136 while ((c = *value) &&
137 (( quoted && c != '"') ||
138 (!quoted && Auth_is_token_char(c)))) {
139 dStr_append_c(result, (c == '\\' && value[1]) ? *++value : c);
140 value++;
141 }
142
143 if (quoted && *value == '\"')
144 value++;
145 *valuep = value;
146 return result;
147 }
148
149 typedef int (Auth_parse_token_value_callback_t)(AuthParse_t *auth_parse,
150 char *token,
151 const char *value);
152
153
154 /*
155 * Parse authentication challenge into token-value pairs
156 * and feed them into the callback function.
157 *
158 * The parsing is aborted should the callback function return 0.
159 *
123160 * Return: 1 if the parse succeeds, 0 otherwise.
124161 */
125 static int Auth_parse_quoted_string(AuthParse_t *auth_parse, int set_realm,
126 char **auth)
127 {
128 char *value;
129 int size;
130
131 /* parse the '"' */
132 switch (*(*auth)++) {
133 case '"':
134 break;
135 case '\0':
136 case ',':
137 MSG("auth.c: missing Basic auth token value after '='\n");
138 return 0;
139 break;
140 default:
141 MSG("auth.c: garbage in Basic auth after '='\n");
142 return 0;
143 break;
144 }
145
146 /* parse the rest */
147 value = *auth;
148 size = 0;
149 while (1) {
162 static int Auth_parse_token_value(AuthParse_t *auth_parse, char **auth,
163 Auth_parse_token_value_callback_t *callback)
164 {
165 char keep_going, expect_quoted;
166 char *token, *beyond_token;
167 Dstr *value;
168 size_t *token_size;
169
170 while (**auth) {
171 _MSG("Auth_parse_token_value: remaining: %s\n", *auth);
172
173 /* parse a token */
174 token = *auth;
175
176 token_size = 0;
177 while (Auth_is_token_char(**auth)) {
178 (*auth)++;
179 token_size++;
180 }
181 if (token_size == 0) {
182 MSG("Auth_parse_token_value: missing auth token\n");
183 return 0;
184 }
185 beyond_token = *auth;
186 /* skip linear whitespace characters */
187 while (**auth == ' ' || **auth == '\t')
188 (*auth)++;
189
190 /* parse the '=' */
150191 switch (*(*auth)++) {
151 case '"':
152 if (set_realm) {
153 dFree((void *)auth_parse->realm);
154 auth_parse->realm = Auth_unquote_value(value, size);
155 auth_parse->ok = 1;
156 }
157 return 1;
192 case '=':
193 *beyond_token = '\0';
158194 break;
159195 case '\0':
160 MSG("auth.c: auth string ended inside quoted string value\n");
196 case ',':
197 MSG("Auth_parse_token_value: missing auth token value\n");
161198 return 0;
162199 break;
163 case '\\':
164 /* end of string? */
165 if (!*(*auth)++) {
166 MSG("auth.c: "
167 "auth string ended inside quoted string value "
168 "immediately after \\\n");
169 return 0;
200 default:
201 MSG("Auth_parse_token_value: garbage after auth token\n");
202 return 0;
203 break;
204 }
205
206 value = Auth_unquote_value(auth);
207 expect_quoted = !(strcmp(token, "stale") == 0 ||
208 strcmp(token, "algorithm") == 0);
209
210 if (((*auth)[-1] == '"') != expect_quoted)
211 MSG_WARN("Auth_parse_token_value: "
212 "Values for key %s should%s be quoted.\n",
213 token, expect_quoted ? "" : " not");
214
215 keep_going = callback(auth_parse, token, value->str);
216 dStr_free(value, 1);
217 if (!keep_going)
218 break;
219
220 /* skip ' ' and ',' */
221 while ((**auth == ' ') || (**auth == ','))
222 (*auth)++;
223 }
224 return 1;
225 }
226
227 static int Auth_parse_basic_challenge_cb(AuthParse_t *auth_parse, char *token,
228 const char *value)
229 {
230 if (dStrAsciiCasecmp("realm", token) == 0) {
231 if (!auth_parse->realm)
232 auth_parse->realm = strdup(value);
233 return 0; /* end parsing */
234 } else
235 MSG("Auth_parse_basic_challenge_cb: Ignoring unknown parameter: %s = "
236 "'%s'\n", token, value);
237 return 1;
238 }
239
240 static int Auth_parse_digest_challenge_cb(AuthParse_t *auth_parse, char *token,
241 const char *value)
242 {
243 const char *const fn = "Auth_parse_digest_challenge_cb";
244
245 if (!dStrAsciiCasecmp("realm", token) && !auth_parse->realm)
246 auth_parse->realm = strdup(value);
247 else if (!strcmp("domain", token) && !auth_parse->domain)
248 auth_parse->domain = strdup(value);
249 else if (!strcmp("nonce", token) && !auth_parse->nonce)
250 auth_parse->nonce = strdup(value);
251 else if (!strcmp("opaque", token) && !auth_parse->opaque)
252 auth_parse->opaque = strdup(value);
253 else if (strcmp("stale", token) == 0) {
254 if (dStrAsciiCasecmp("true", value) == 0)
255 auth_parse->stale = 1;
256 else if (dStrAsciiCasecmp("false", value) == 0)
257 auth_parse->stale = 0;
258 else {
259 MSG("%s: Invalid stale value: %s\n", fn, value);
260 return 0;
261 }
262 } else if (strcmp("algorithm", token) == 0) {
263 if (strcmp("MD5", value) == 0)
264 auth_parse->algorithm = MD5;
265 else if (strcmp("MD5-sess", value) == 0) {
266 /* auth_parse->algorithm = MD5SESS; */
267 MSG("%s: MD5-sess algorithm disabled (not tested because 'not "
268 "correctly implemented yet' in Apache 2.2)\n", fn);
269 return 0;
270 } else {
271 MSG("%s: Unknown algorithm: %s\n", fn, value);
272 return 0;
273 }
274 } else if (strcmp("qop", token) == 0) {
275 while (*value) {
276 int len = strcspn(value, ", \t");
277 if (len == 4 && strncmp("auth", value, 4) == 0) {
278 auth_parse->qop = AUTH;
279 break;
170280 }
171 /* fall through to the next case */
172 default:
173 size++;
174 break;
175 }
176 }
177 }
178
179 /*
180 * Parse a token-value pair.
181 * Return: 1 if the parse succeeds, 0 otherwise.
182 */
183 static int Auth_parse_token_value(AuthParse_t *auth_parse, char **auth)
184 {
185 char *token;
186 int token_size, set_realm;
187 static const char realm_token[] = "realm";
188
189 /* parse a token */
190 token = *auth;
191 token_size = 0;
192 while (Auth_is_token_char(**auth)) {
193 (*auth)++;
194 token_size++;
195 }
196 if (token_size == 0) {
197 MSG("auth.c: Auth_parse_token_value: "
198 "missing Basic auth token\n");
199 return 0;
200 }
201
202 /* skip space characters */
203 while (**auth == ' ')
204 (*auth)++;
205
206 /* parse the '=' */
207 switch (*(*auth)++) {
208 case '=':
209 break;
210 case '\0':
211 case ',':
212 MSG("auth.c: Auth_parse_token_value: "
213 "missing Basic auth token value\n");
214 return 0;
215 break;
216 default:
217 MSG("auth.c: Auth_parse_token_value: "
218 "garbage after Basic auth token\n");
219 return 0;
220 break;
221 }
222
223 /* skip space characters */
224 while (**auth == ' ')
225 (*auth)++;
226
227 /* is this value the realm? */
228 set_realm =
229 auth_parse->realm == NULL &&
230 dStrncasecmp(realm_token,token,token_size) == 0 &&
231 strlen(realm_token) == (size_t)token_size;
232
233 return Auth_parse_quoted_string(auth_parse, set_realm, auth);
234 }
235
236 static void Auth_parse_auth_basic(AuthParse_t *auth_parse, char **auth)
237 {
238 int token_value_pairs_found;
239
281 if (len == 8 && strncmp("auth-int", value, 8) == 0) {
282 /* auth_parse->qop = AUTHINT; */
283 /* Keep searching; maybe we'll find an "auth" yet. */
284 MSG("%s: auth-int qop disabled (not tested because 'not "
285 "implemented yet' in Apache 2.2)\n", fn);
286 } else {
287 MSG("%s: Unknown qop value in %s\n", fn, value);
288 }
289 value += len;
290 while (*value == ' ' || *value == '\t')
291 value++;
292 if (*value == ',')
293 value++;
294 while (*value == ' ' || *value == '\t')
295 value++;
296 }
297 } else {
298 MSG("%s: Ignoring unknown parameter: %s = '%s'\n", fn, token, value);
299 }
300 return 1;
301 }
302
303 static void Auth_parse_challenge_args(AuthParse_t *auth_parse,
304 char **challenge,
305 Auth_parse_token_value_callback_t *cb)
306 {
240307 /* parse comma-separated token-value pairs */
241 token_value_pairs_found = 0;
242308 while (1) {
243309 /* skip space and comma characters */
244 while (**auth == ' ' || **auth == ',')
245 (*auth)++;
310 while (**challenge == ' ' || **challenge == ',')
311 (*challenge)++;
246312 /* end of string? */
247 if (!**auth)
313 if (!**challenge)
248314 break;
249315 /* parse token-value pair */
250 if (!Auth_parse_token_value(auth_parse, auth))
316 if (!Auth_parse_token_value(auth_parse, challenge, cb))
251317 break;
252 token_value_pairs_found = 1;
253 }
254
255 if (!token_value_pairs_found) {
256 MSG("auth.c: Auth_parse_auth_basic: "
257 "missing Basic auth token-value pairs\n");
258 return;
259 }
260
261 if (!auth_parse->realm) {
262 MSG("auth.c: Auth_parse_auth_basic: "
263 "missing Basic auth realm\n");
264 return;
265 }
266 }
267
268 static void Auth_parse_auth(AuthParse_t *auth_parse, char *auth)
269 {
270 _MSG("auth.c: Auth_parse_auth: auth = '%s'\n", auth);
271 if (dStrncasecmp(auth, "Basic ", 6) == 0) {
272 auth += 6;
273 Auth_parse_auth_basic(auth_parse, &auth);
318 }
319
320 if (auth_parse->type == BASIC) {
321 if (auth_parse->realm) {
322 auth_parse->ok = 1;
323 } else {
324 MSG("Auth_parse_challenge_args: missing Basic auth realm\n");
325 return;
326 }
327 } else if (auth_parse->type == DIGEST) {
328 if (auth_parse->realm && auth_parse->nonce) {
329 auth_parse->ok = 1;
330 } else {
331 MSG("Auth_parse_challenge_args: Digest challenge incomplete\n");
332 return;
333 }
334 }
335 }
336
337 static void Auth_parse_challenge(AuthParse_t *auth_parse, char *challenge)
338 {
339 Auth_parse_token_value_callback_t *cb;
340
341 MSG("auth.c: Auth_parse_challenge: challenge = '%s'\n", challenge);
342 if (auth_parse->type == DIGEST) {
343 challenge += 7;
344 cb = Auth_parse_digest_challenge_cb;
274345 } else {
275 MSG("auth.c: Auth_parse_auth: "
276 "unknown authorization scheme: auth = {%s}\n",
277 auth);
278 }
346 challenge += 6;
347 cb = Auth_parse_basic_challenge_cb;
348 }
349 Auth_parse_challenge_args(auth_parse, &challenge, cb);
279350 }
280351
281352 /*
287358 int i;
288359
289360 for (i = 0; (host = dList_nth_data(auth_hosts, i)); i++)
290 if (((dStrcasecmp(URL_SCHEME(url), host->scheme) == 0) &&
291 (dStrcasecmp(URL_AUTHORITY(url), host->authority) == 0)))
361 if (((dStrAsciiCasecmp(URL_SCHEME(url), host->scheme) == 0) &&
362 (dStrAsciiCasecmp(URL_AUTHORITY(url), host->authority) == 0)))
292363 return host;
293364
294365 return NULL;
304375 int i;
305376
306377 for (i = 0; (realm = dList_nth_data(host->realms, i)); i++)
307 if (strcmp(realm->name,name) == 0)
378 if (strcmp(realm->name, name) == 0)
308379 return realm;
309380
310381 return NULL;
318389 {
319390 AuthRealm_t *realm_best, *realm;
320391 int i, j;
321 int match_length;
322
323 match_length = 0;
392 int match_length = 0;
393
324394 realm_best = NULL;
325395 for (i = 0; (realm = dList_nth_data(host->realms, i)); i++) {
326396 char *realm_path;
338408 return realm_best;
339409 }
340410
411 static void Auth_realm_delete(AuthRealm_t *realm)
412 {
413 int i;
414
415 MSG("Auth_realm_delete: \"%s\"\n", realm->name);
416 for (i = dList_length(realm->paths) - 1; i >= 0; i--)
417 dFree(dList_nth_data(realm->paths, i));
418 dList_free(realm->paths);
419 dFree(realm->name);
420 dFree(realm->username);
421 dFree(realm->authorization);
422 dFree(realm->cnonce);
423 dFree(realm->nonce);
424 dFree(realm->opaque);
425 dFree(realm->domain);
426 dFree(realm);
427 }
428
341429 static int Auth_realm_includes_path(const AuthRealm_t *realm, const char *path)
342430 {
343431 int i;
376464
377465 /*
378466 * Return the authorization header for an HTTP query.
379 */
380 const char *a_Auth_get_auth_str(const DilloUrl *url)
381 {
467 * request_uri is a separate argument because we want it precisely as
468 * formatted in the request.
469 */
470 char *a_Auth_get_auth_str(const DilloUrl *url, const char *request_uri)
471 {
472 char *ret = NULL;
382473 AuthHost_t *host;
383474 AuthRealm_t *realm;
384475
385 return
386 ((host = Auth_host_by_url(url)) &&
387 (realm = Auth_realm_by_path(host, URL_PATH(url)))) ?
388 realm->authorization : NULL;
476 if ((host = Auth_host_by_url(url)) &&
477 (realm = Auth_realm_by_path(host, URL_PATH(url)))) {
478 if (realm->type == BASIC)
479 ret = dStrdup(realm->authorization);
480 else if (realm->type == DIGEST)
481 ret = a_Digest_authorization_hdr(realm, url, request_uri);
482 else
483 MSG("a_Auth_get_auth_str() got an unknown realm type: %i.\n",
484 realm->type);
485 }
486 return ret;
389487 }
390488
391489 /*
392490 * Determine whether the user needs to authenticate.
393491 */
394 static int Auth_do_auth_required(const char *realm_name, const DilloUrl *url)
492 static int Auth_do_auth_required(const AuthParse_t *auth_parse,
493 const DilloUrl *url)
395494 {
396495 /*
397496 * TO DO: I dislike the way that this code must decide whether we
419518 * we will re-authenticate.
420519 */
421520 if ((host = Auth_host_by_url(url)) &&
422 (realm = Auth_realm_by_name(host, realm_name)) &&
423 (!Auth_realm_includes_path(realm, URL_PATH(url)))) {
424 _MSG("Auth_do_auth_required: updating realm '%s' with URL '%s'\n",
425 realm_name, URL_STR(url));
426 Auth_realm_add_path(realm, URL_PATH(url));
427 return 0;
521 (realm = Auth_realm_by_name(host, auth_parse->realm))) {
522 if (!Auth_realm_includes_path(realm, URL_PATH(url))) {
523 _MSG("Auth_do_auth_required: updating realm '%s' with URL '%s'\n",
524 auth_parse->realm, URL_STR(url));
525 Auth_realm_add_path(realm, URL_PATH(url));
526 return 0;
527 }
528
529 if (auth_parse->type == DIGEST && auth_parse->stale) {
530 /* we do have valid credentials but our nonce is old */
531 dFree((void *)realm->nonce);
532 realm->nonce = dStrdup(auth_parse->nonce);
533 return 0;
534 }
428535 }
429536
430537 /*
440547 AuthDialogData_t *data;
441548 AuthHost_t *host;
442549 AuthRealm_t *realm;
443 char *user_password, *response, *authorization, *authorization_old;
444550
445551 data = (AuthDialogData_t *)vData;
446552
455561 }
456562
457563 /* find or create the realm */
458 if (!(realm = Auth_realm_by_name(host, data->realm_name))) {
459 /* create a new realm */
460 realm = dNew(AuthRealm_t, 1);
461 realm->name = dStrdup(data->realm_name);
564 if (!(realm = Auth_realm_by_name(host, data->auth_parse->realm))) {
565 realm = dNew0(AuthRealm_t, 1);
566 realm->name = dStrdup(data->auth_parse->realm);
462567 realm->paths = dList_new(1);
463 realm->authorization = NULL;
464568 dList_append(host->realms, realm);
465569 }
570 realm->type = data->auth_parse->type;
571 dFree(realm->authorization);
572 realm->authorization = NULL;
466573
467574 Auth_realm_add_path(realm, URL_PATH(data->url));
468575
469 /* create and set the authorization */
470 user_password = dStrconcat(user, ":", password, NULL);
471 response = a_Misc_encode_base64(user_password);
472 authorization =
473 dStrconcat("Authorization: Basic ", response, "\r\n", NULL);
474 authorization_old = realm->authorization;
475 realm->authorization = authorization;
476 dFree(authorization_old);
477 dFree(user_password);
478 dFree(response);
479 }
480
481 static int Auth_do_auth_dialog(const char *realm, const DilloUrl *url)
576 if (realm->type == BASIC) {
577 char *user_password = dStrconcat(user, ":", password, NULL);
578 char *response = a_Misc_encode_base64(user_password);
579 char *authorization =
580 dStrconcat("Authorization: Basic ", response, "\r\n", NULL);
581 dFree(realm->authorization);
582 realm->authorization = authorization;
583 dFree(response);
584 dStrshred(user_password);
585 dFree(user_password);
586 } else if (realm->type == DIGEST) {
587 dFree(realm->username);
588 realm->username = dStrdup(user);
589 realm->nonce_count = 0;
590 dFree(realm->nonce);
591 realm->nonce = dStrdup(data->auth_parse->nonce);
592 dFree(realm->opaque);
593 realm->opaque = dStrdup(data->auth_parse->opaque);
594 realm->algorithm = data->auth_parse->algorithm;
595 dFree(realm->domain);
596 realm->domain = dStrdup(data->auth_parse->domain);
597 realm->qop = data->auth_parse->qop;
598 dFree(realm->cnonce);
599 if (realm->qop != QOPNOTSET)
600 realm->cnonce = a_Digest_create_cnonce();
601 if (!a_Digest_compute_digest(realm, user, password)) {
602 MSG("Auth_do_auth_dialog_cb: a_Digest_compute_digest failed.\n");
603 dList_remove_fast(host->realms, realm);
604 Auth_realm_delete(realm);
605 }
606 } else {
607 MSG("Auth_do_auth_dialog_cb: Unknown auth type: %i\n",
608 realm->type);
609 }
610 dStrshred((char *)password);
611 }
612
613 /*
614 * Return: Nonzero if we got new credentials from the user and everything
615 * seems fine.
616 */
617 static int Auth_do_auth_dialog(const AuthParse_t *auth_parse,
618 const DilloUrl *url)
482619 {
483620 int ret;
484621 char *message;
485622 AuthDialogData_t *data;
486
487 _MSG("auth.c: Auth_do_auth_dialog: realm = '%s'\n", realm);
623 const char *typestr = auth_parse->type == DIGEST ? "Digest" : "Basic";
624
625 _MSG("auth.c: Auth_do_auth_dialog: realm = '%s'\n", auth_parse->realm);
626
488627 message = dStrconcat("The server at ", URL_HOST(url), " requires a username"
489 " and password for \"", realm, "\".", NULL);
628 " and password for \"", auth_parse->realm, "\".\n\n"
629 "Authentication scheme: ", typestr, NULL);
490630 data = dNew(AuthDialogData_t, 1);
491 data->realm_name = dStrdup(realm);
631 data->auth_parse = auth_parse;
492632 data->url = a_Url_dup(url);
493633 ret = a_Dialog_user_password(message, Auth_do_auth_dialog_cb, data);
494634 dFree(message);
495 dFree((void*)data->realm_name);
496 a_Url_free((void*)data->url);
635 a_Url_free((void *)data->url);
497636 dFree(data);
498637 return ret;
499638 }
501640 /*
502641 * Do authorization for an auth string.
503642 */
504 static int Auth_do_auth(char *auth, const DilloUrl *url)
505 {
506 int reload;
643 static int Auth_do_auth(char *challenge, enum AuthParseHTTPAuthType_t type,
644 const DilloUrl *url)
645 {
507646 AuthParse_t *auth_parse;
508
509 _MSG("auth.c: Auth_do_auth: auth={%s}\n", auth);
510 reload = 0;
647 int reload = 0;
648
649 _MSG("auth.c: Auth_do_auth: challenge={%s}\n", challenge);
511650 auth_parse = Auth_parse_new();
512 Auth_parse_auth(auth_parse, auth);
651 auth_parse->type = type;
652 Auth_parse_challenge(auth_parse, challenge);
513653 if (auth_parse->ok)
514654 reload =
515 Auth_do_auth_required(auth_parse->realm, url) ?
516 Auth_do_auth_dialog(auth_parse->realm, url)
655 Auth_do_auth_required(auth_parse, url) ?
656 Auth_do_auth_dialog(auth_parse, url)
517657 : 1;
518658 Auth_parse_free(auth_parse);
519659
521661 }
522662
523663 /*
524 * Do authorization for a set of auth strings.
525 */
526 int a_Auth_do_auth(Dlist *auths, const DilloUrl *url)
527 {
528 int reload, i;
529 char *auth;
530
531 reload = 0;
532 for (i = 0; (auth = dList_nth_data(auths, i)); ++i)
533 if (Auth_do_auth(auth, url))
534 reload = 1;
535
536 return reload;
537 }
538
664 * Given authentication challenge(s), prepare authorization.
665 * Return: 0 on failure
666 * nonzero on success. A new query will be sent to the server.
667 */
668 int a_Auth_do_auth(Dlist *challenges, const DilloUrl *url)
669 {
670 int i;
671 char *chal;
672
673 for (i = 0; (chal = dList_nth_data(challenges, i)); ++i)
674 if (!dStrnAsciiCasecmp(chal, "Digest ", 7))
675 if (Auth_do_auth(chal, DIGEST, url))
676 return 1;
677 for (i = 0; (chal = dList_nth_data(challenges, i)); ++i)
678 if (!dStrnAsciiCasecmp(chal, "Basic ", 6))
679 if (Auth_do_auth(chal, BASIC, url))
680 return 1;
681
682 return 0;
683 }
684
66
77 #include "url.h"
88
9 enum AuthParseHTTPAuthType_t { TYPENOTSET, BASIC, DIGEST };
10 enum AuthParseDigestAlgorithm_t { ALGORITHMNOTSET, MD5, MD5SESS };
11 enum AuthParseDigestQOP_t { QOPNOTSET, AUTH, AUTHINT };
912
10 const char *a_Auth_get_auth_str(const DilloUrl *request_url);
13 typedef struct {
14 enum AuthParseHTTPAuthType_t type;
15 char *name;
16 Dlist *paths; /* stripped of any trailing '/', so the root path is "" */
17 char *authorization; /* BASIC: the authorization request header */
18 /* DIGEST: the hexdigest of A1 */
19 /* digest state ahead */
20 char *username;
21 char *cnonce;
22 unsigned int nonce_count;
23 char *nonce;
24 char *opaque;
25 enum AuthParseDigestAlgorithm_t algorithm;
26 char *domain; /* NOT USED */
27 enum AuthParseDigestQOP_t qop;
28 } AuthRealm_t;
29
30
31 char *a_Auth_get_auth_str(const DilloUrl *url, const char *request_uri);
1132 int a_Auth_do_auth(Dlist *auth_string, const DilloUrl *url);
1233 void a_Auth_init(void);
1334
00 #ifndef __BINARYCONST_H__
11 #define __BINARYCONST_H__
2
3 /* binaryconst.h was integrated into the Dillo project in April 2004, and
4 * presumably comes from the ancestor of the code found at
5 * http://cprog.tomsweb.net/binconst.txt
6 */
27
38 /* Macros for allowing binary constants in C
49 * By Tom Torfs - donated to the public domain */
1212 * Dillo's cache module
1313 */
1414
15 #include <ctype.h> /* for tolower */
1615 #include <sys/types.h>
1716
1817 #include <stdlib.h>
520519 /* META only gives charset; use detected MIME type too */
521520 entry->TypeNorm = dStrconcat(entry->TypeDet, ctype, NULL);
522521 } else if (*from == 'm' &&
523 !dStrncasecmp(ctype, "text/xhtml", 10)) {
522 !dStrnAsciiCasecmp(ctype, "text/xhtml", 10)) {
524523 /* WORKAROUND: doxygen uses "text/xhtml" in META */
525524 entry->TypeNorm = dStrdup(entry->TypeDet);
526525 }
583582 for (i = 0; header[i]; i++) {
584583 /* Search fieldname */
585584 for (j = 0; fieldname[j]; j++)
586 if (tolower(fieldname[j]) != tolower(header[i + j]))
585 if (D_ASCII_TOLOWER(fieldname[j]) != D_ASCII_TOLOWER(header[i + j]))
587586 break;
588587 if (fieldname[j]) {
589588 /* skip to next line */
619618 for (i = 0; header[i]; i++) {
620619 /* Search fieldname */
621620 for (j = 0; fieldname[j]; j++)
622 if (tolower(fieldname[j]) != tolower(header[i + j]))
621 if (D_ASCII_TOLOWER(fieldname[j]) != D_ASCII_TOLOWER(header[i + j]))
623622 break;
624623 if (fieldname[j]) {
625624 /* skip to next line */
674673 entry->Header = dStr_new("");
675674 return;
676675 }
677 if (header[9] == '3' && header[10] == '0') {
676 if (header[9] == '3' && header[10] == '0' &&
677 (location_str = Cache_parse_field(header, "Location"))) {
678678 /* 30x: URL redirection */
679 if ((location_str = Cache_parse_field(header, "Location"))) {
680 DilloUrl *location_url;
681
679 DilloUrl *location_url = a_Url_new(location_str,URL_STR_(entry->Url));
680
681 if (prefs.filter_auto_requests == PREFS_FILTER_SAME_DOMAIN &&
682 !a_Url_same_organization(entry->Url, location_url)) {
683 /* don't redirect; just show body like usual (if any) */
684 MSG("Redirection not followed from %s to %s\n",
685 URL_HOST(entry->Url), URL_STR(location_url));
686 a_Url_free(location_url);
687 } else {
682688 entry->Flags |= CA_Redirect;
683689 if (header[11] == '1')
684690 entry->Flags |= CA_ForceRedirect; /* 301 Moved Permanently */
685691 else if (header[11] == '2')
686692 entry->Flags |= CA_TempRedirect; /* 302 Temporary Redirect */
687693
688 location_url = a_Url_new(location_str, URL_STR_(entry->Url));
689694 if (URL_FLAGS(location_url) & (URL_Post + URL_Get) &&
690 dStrcasecmp(URL_SCHEME(location_url), "dpi") == 0 &&
691 dStrcasecmp(URL_SCHEME(entry->Url), "dpi") != 0) {
695 dStrAsciiCasecmp(URL_SCHEME(location_url), "dpi") == 0 &&
696 dStrAsciiCasecmp(URL_SCHEME(entry->Url), "dpi") != 0) {
692697 /* Forbid dpi GET and POST from non dpi-generated urls */
693698 MSG("Redirection Denied! '%s' -> '%s'\n",
694699 URL_STR(entry->Url), URL_STR(location_url));
696701 } else {
697702 entry->Location = location_url;
698703 }
699 dFree(location_str);
700 }
704 }
705 dFree(location_str);
701706 } else if (strncmp(header + 9, "401", 3) == 0) {
702707 entry->Auth =
703708 Cache_parse_multiple_fields(header, "WWW-Authenticate");
727732 * If Transfer-Encoding is present, Content-Length must be ignored.
728733 * If the Transfer-Encoding is non-identity, it is an error.
729734 */
730 if (dStrcasecmp(encoding, "identity"))
735 if (dStrAsciiCasecmp(encoding, "identity"))
731736 MSG_HTTP("Content-Length and non-identity Transfer-Encoding "
732737 "headers both present.\n");
733738 } else {
10381043 */
10391044 int a_Cache_download_enabled(const DilloUrl *url)
10401045 {
1041 if (!dStrcasecmp(URL_SCHEME(url), "http") ||
1042 !dStrcasecmp(URL_SCHEME(url), "https") ||
1043 !dStrcasecmp(URL_SCHEME(url), "ftp"))
1046 if (!dStrAsciiCasecmp(URL_SCHEME(url), "http") ||
1047 !dStrAsciiCasecmp(URL_SCHEME(url), "https") ||
1048 !dStrAsciiCasecmp(URL_SCHEME(url), "ftp"))
10441049 return 1;
10451050 return 0;
10461051 }
228228 const DilloUrl *referer;
229229 int allow = FALSE;
230230
231 if (dStrcasecmp(URL_SCHEME(url), "dpi") == 0) {
231 if (dStrAsciiCasecmp(URL_SCHEME(url), "dpi") == 0) {
232232 if (!(URL_FLAGS(url) & (URL_Post + URL_Get))) {
233233 allow = TRUE;
234234 } else if (!(URL_FLAGS(url) & URL_Post) &&
235 strncmp(URL_STR(url), "dpi:/vsource/", 13) == 0) {
235 strncmp(URL_PATH(url), "/vsource/", 9) == 0) {
236236 allow = TRUE;
237237 } else {
238238 /* only allow GET&POST dpi-requests from dpi-generated urls */
239239 if (a_Nav_stack_size(bw)) {
240240 referer = a_History_get_url(NAV_TOP_UIDX(bw));
241 if (dStrcasecmp(URL_SCHEME(referer), "dpi") == 0) {
241 if (dStrAsciiCasecmp(URL_SCHEME(referer), "dpi") == 0) {
242242 allow = TRUE;
243243 }
244244 }
265265 char *p, *server = NULL, *url_str = URL_STR(url);
266266 Dstr *tmp;
267267
268 if ((dStrncasecmp(url_str, "http:", 5) == 0) ||
269 (dStrncasecmp(url_str, "about:", 6) == 0)) {
268 if ((dStrnAsciiCasecmp(url_str, "http:", 5) == 0) ||
269 (dStrnAsciiCasecmp(url_str, "about:", 6) == 0)) {
270270 /* URL doesn't use dpi (server = NULL) */
271 } else if (dStrncasecmp(url_str, "dpi:/", 5) == 0) {
271 } else if (dStrnAsciiCasecmp(url_str, "dpi:/", 5) == 0) {
272272 /* dpi prefix, get this server's name */
273273 if ((p = strchr(url_str + 5, '/')) != NULL) {
274274 server = dStrndup(url_str + 5, (uint_t)(p - url_str - 5));
387387 *want_host = URL_HOST(wanted);
388388 if (want_host[0] == '\0') {
389389 ret = (req_host[0] == '\0' ||
390 !dStrcasecmp(URL_SCHEME(wanted), "data")) ? TRUE : FALSE;
390 !dStrAsciiCasecmp(URL_SCHEME(wanted), "data"))
391 ? TRUE : FALSE;
391392 } else {
392393 /* This will regard "www.dillo.org" and "www.dillo.org." as
393394 * different, but it doesn't seem worth caring about.
453454 } else if (Capi_url_uses_dpi(web->url, &server)) {
454455 /* dpi request */
455456 if ((safe = a_Capi_dpi_verify_request(web->bw, web->url))) {
456 if (dStrcasecmp(scheme, "dpi") == 0) {
457 if (dStrAsciiCasecmp(scheme, "dpi") == 0) {
457458 if (strcmp(server, "vsource") == 0) {
458 /* don't reload the "view source" page */
459 /* allow "view source" reload upon user request */
459460 } else {
460461 /* make the other "dpi:/" prefixed urls always reload. */
461462 a_Url_set_flags(web->url, URL_FLAGS(web->url) | URL_E2EQuery);
477478 }
478479 dFree(server);
479480
480 } else if (!dStrcasecmp(scheme, "http")) {
481 } else if (!dStrAsciiCasecmp(scheme, "http")) {
481482 /* http request */
482483 if (reload) {
483484 a_Capi_conn_abort_by_url(web->url);
490491 }
491492 use_cache = 1;
492493
493 } else if (!dStrcasecmp(scheme, "about")) {
494 } else if (!dStrAsciiCasecmp(scheme, "about")) {
494495 /* internal request */
495496 use_cache = 1;
496497 }
261261 high = NCOLORS - 1;
262262 while (low <= high) {
263263 mid = (low + high) / 2;
264 if ((ret = dStrcasecmp(cp, color_keyword[mid].key)) < 0)
264 if ((ret = dStrAsciiCasecmp(cp, color_keyword[mid].key)) < 0)
265265 high = mid - 1;
266266 else if (ret > 0)
267267 low = mid + 1;
283283 rule[j++] = line[i++];
284284 rule[j] = '\0';
285285
286 if (dStrcasecmp(rule, "ACCEPT") == 0)
286 if (dStrAsciiCasecmp(rule, "ACCEPT") == 0)
287287 cc.action = COOKIE_ACCEPT;
288 else if (dStrcasecmp(rule, "ACCEPT_SESSION") == 0)
288 else if (dStrAsciiCasecmp(rule, "ACCEPT_SESSION") == 0)
289289 cc.action = COOKIE_ACCEPT_SESSION;
290 else if (dStrcasecmp(rule, "DENY") == 0)
290 else if (dStrAsciiCasecmp(rule, "DENY") == 0)
291291 cc.action = COOKIE_DENY;
292292 else {
293293 MSG("Cookies: rule '%s' for domain '%s' is not recognised.\n",
296296 }
297297
298298 cc.domain = dStrdup(domain);
299 if (dStrcasecmp(cc.domain, "DEFAULT") == 0) {
299 if (dStrAsciiCasecmp(cc.domain, "DEFAULT") == 0) {
300300 /* Set the default action */
301301 default_action = cc.action;
302302 dFree(cc.domain);
337337 if (ccontrol[i].domain[0] == '.') {
338338 diff = strlen(domain) - strlen(ccontrol[i].domain);
339339 if (diff >= 0) {
340 if (dStrcasecmp(domain + diff, ccontrol[i].domain) != 0)
340 if (dStrAsciiCasecmp(domain + diff, ccontrol[i].domain) != 0)
341341 continue;
342342 } else {
343343 continue;
344344 }
345345 } else {
346 if (dStrcasecmp(domain, ccontrol[i].domain) != 0)
346 if (dStrAsciiCasecmp(domain, ccontrol[i].domain) != 0)
347347 continue;
348348 }
349349
264264 if (element != ELEMENT_ANY && element != n->element)
265265 return false;
266266 if (pseudo != NULL &&
267 (n->pseudo == NULL || dStrcasecmp (pseudo, n->pseudo) != 0))
267 (n->pseudo == NULL || dStrAsciiCasecmp (pseudo, n->pseudo) != 0))
268268 return false;
269 if (id != NULL && (n->id == NULL || dStrcasecmp (id, n->id) != 0))
269 if (id != NULL && (n->id == NULL || dStrAsciiCasecmp (id, n->id) != 0))
270270 return false;
271271 if (klass != NULL) {
272272 for (int i = 0; i < klass->size (); i++) {
273273 bool found = false;
274274 if (n->klass != NULL) {
275275 for (int j = 0; j < n->klass->size (); j++) {
276 if (dStrcasecmp (klass->get(i), n->klass->get(j)) == 0) {
276 if (dStrAsciiCasecmp (klass->get(i), n->klass->get(j)) == 0) {
277277 found = true;
278278 break;
279279 }
609609 "th {font-weight: bolder; text-align: center}"
610610 "code, tt, pre, samp, kbd {font-family: monospace}"
611611 /* WORKAROUND: Reset font properties in tables as some
612 * some pages rely on it (e.g. gmail).
612 * pages rely on it (e.g. gmail).
613613 * http://developer.mozilla.org/En/Fixing_Table_Inheritance_in_Quirks_Mode
614614 * has a detailed description of the issue.
615615 */
118118
119119 static const char *const Css_text_decoration_enum_vals[] = {
120120 "underline", "overline", "line-through", "blink", NULL
121 };
122
123 static const char *const Css_text_transform_enum_vals[] = {
124 "none", "capitalize", "uppercase", "lowercase", NULL
121125 };
122126
123127 static const char *const Css_vertical_align_vals[] = {
227231 Css_text_decoration_enum_vals},
228232 {"text-indent", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_UNUSED}, NULL},
229233 {"text-shadow", {CSS_TYPE_UNUSED}, NULL},
230 {"text-transform", {CSS_TYPE_UNUSED}, NULL},
234 {"text-transform", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED},
235 Css_text_transform_enum_vals},
231236 {"top", {CSS_TYPE_UNUSED}, NULL},
232237 {"unicode-bidi", {CSS_TYPE_UNUSED}, NULL},
233238 {"vertical-align",{CSS_TYPE_ENUM, CSS_TYPE_UNUSED},Css_vertical_align_vals},
668673 case CSS_TYPE_ENUM:
669674 if (ttype == CSS_TK_SYMBOL) {
670675 for (i = 0; Css_property_info[prop].enum_symbols[i]; i++)
671 if (dStrcasecmp(tval,
676 if (dStrAsciiCasecmp(tval,
672677 Css_property_info[prop].enum_symbols[i]) == 0)
673678 return true;
674679 }
676681
677682 case CSS_TYPE_MULTI_ENUM:
678683 if (ttype == CSS_TK_SYMBOL) {
679 if (dStrcasecmp(tval, "none") == 0) {
684 if (dStrAsciiCasecmp(tval, "none") == 0) {
680685 return true;
681686 } else {
682687 for (i = 0; Css_property_info[prop].enum_symbols[i]; i++) {
683 if (dStrcasecmp(tval,
688 if (dStrAsciiCasecmp(tval,
684689 Css_property_info[prop].enum_symbols[i]) == 0)
685690 return true;
686691 }
697702 case CSS_TYPE_SIGNED_LENGTH:
698703 if (ttype == CSS_TK_DECINT ||
699704 ttype == CSS_TK_FLOAT ||
700 (ttype == CSS_TK_SYMBOL && dStrcasecmp(tval, "auto") == 0))
705 (ttype == CSS_TK_SYMBOL && dStrAsciiCasecmp(tval, "auto") == 0))
701706 return true;
702707 break;
703708
704709 case CSS_TYPE_COLOR:
705710 if ((ttype == CSS_TK_COLOR ||
706711 ttype == CSS_TK_SYMBOL) &&
707 (dStrcasecmp(tval, "rgb") == 0 ||
712 (dStrAsciiCasecmp(tval, "rgb") == 0 ||
708713 a_Color_parse(tval, -1, &err) != -1))
709714 return true;
710715 break;
832837 case CSS_TYPE_ENUM:
833838 if (ttype == CSS_TK_SYMBOL) {
834839 for (i = 0; Css_property_info[prop].enum_symbols[i]; i++)
835 if (dStrcasecmp(tval,
840 if (dStrAsciiCasecmp(tval,
836841 Css_property_info[prop].enum_symbols[i]) == 0) {
837842 val->intVal = i;
838843 ret = true;
847852 ret = true;
848853
849854 while (ttype == CSS_TK_SYMBOL) {
850 if (dStrcasecmp(tval, "none") != 0) {
855 if (dStrAsciiCasecmp(tval, "none") != 0) {
851856 for (i = 0, found = false;
852857 !found && Css_property_info[prop].enum_symbols[i]; i++) {
853 if (dStrcasecmp(tval,
858 if (dStrAsciiCasecmp(tval,
854859 Css_property_info[prop].enum_symbols[i]) == 0)
855860 val->intVal |= (1 << i);
856861 }
871876 if (!spaceSeparated && ttype == CSS_TK_SYMBOL) {
872877 ret = true;
873878
874 if (dStrcasecmp(tval, "px") == 0) {
879 if (dStrAsciiCasecmp(tval, "px") == 0) {
875880 lentype = CSS_LENGTH_TYPE_PX;
876881 nextToken();
877 } else if (dStrcasecmp(tval, "mm") == 0) {
882 } else if (dStrAsciiCasecmp(tval, "mm") == 0) {
878883 lentype = CSS_LENGTH_TYPE_MM;
879884 nextToken();
880 } else if (dStrcasecmp(tval, "cm") == 0) {
885 } else if (dStrAsciiCasecmp(tval, "cm") == 0) {
881886 lentype = CSS_LENGTH_TYPE_MM;
882887 fval *= 10;
883888 nextToken();
884 } else if (dStrcasecmp(tval, "in") == 0) {
889 } else if (dStrAsciiCasecmp(tval, "in") == 0) {
885890 lentype = CSS_LENGTH_TYPE_MM;
886891 fval *= 25.4;
887892 nextToken();
888 } else if (dStrcasecmp(tval, "pt") == 0) {
893 } else if (dStrAsciiCasecmp(tval, "pt") == 0) {
889894 lentype = CSS_LENGTH_TYPE_MM;
890895 fval *= (25.4 / 72);
891896 nextToken();
892 } else if (dStrcasecmp(tval, "pc") == 0) {
897 } else if (dStrAsciiCasecmp(tval, "pc") == 0) {
893898 lentype = CSS_LENGTH_TYPE_MM;
894899 fval *= (25.4 / 6);
895900 nextToken();
896 } else if (dStrcasecmp(tval, "em") == 0) {
901 } else if (dStrAsciiCasecmp(tval, "em") == 0) {
897902 lentype = CSS_LENGTH_TYPE_EM;
898903 nextToken();
899 } else if (dStrcasecmp(tval, "ex") == 0) {
904 } else if (dStrAsciiCasecmp(tval, "ex") == 0) {
900905 lentype = CSS_LENGTH_TYPE_EX;
901906 nextToken();
902907 } else {
921926 ret = true;
922927
923928 val->intVal = CSS_CREATE_LENGTH(fval, lentype);
924 } else if (ttype == CSS_TK_SYMBOL && dStrcasecmp(tval, "auto") == 0) {
929 } else if (ttype == CSS_TK_SYMBOL && !dStrAsciiCasecmp(tval, "auto")) {
925930 ret = true;
926931 val->intVal = CSS_LENGTH_TYPE_AUTO;
927932 nextToken();
937942 ret = true;
938943 nextToken();
939944 } else if (ttype == CSS_TK_SYMBOL) {
940 if (dStrcasecmp(tval, "rgb") == 0) {
945 if (dStrAsciiCasecmp(tval, "rgb") == 0) {
941946 nextToken();
942947 if (parseRgbColor(&val->intVal))
943948 ret = true;
10161021 if (ttype == CSS_TK_CHAR && tval[0] == '!') {
10171022 nextToken();
10181023 if (ttype == CSS_TK_SYMBOL &&
1019 dStrcasecmp(tval, "important") == 0) {
1024 dStrAsciiCasecmp(tval, "important") == 0) {
10201025 nextToken();
10211026 return true;
10221027 }
10301035 */
10311036 static int Css_property_info_cmp(const void *a, const void *b)
10321037 {
1033 return dStrcasecmp(((CssPropertyInfo *) a)->symbol,
1038 return dStrAsciiCasecmp(((CssPropertyInfo *) a)->symbol,
10341039 ((CssPropertyInfo *) b)->symbol);
10351040 }
10361041
10401045 */
10411046 static int Css_shorthand_info_cmp(const void *a, const void *b)
10421047 {
1043 return dStrcasecmp(((CssShorthandInfo *) a)->symbol,
1048 return dStrAsciiCasecmp(((CssShorthandInfo *) a)->symbol,
10441049 ((CssShorthandInfo *) b)->symbol);
10451050 }
10461051
13851390 Dstr *urlStr = NULL;
13861391
13871392 if (ttype != CSS_TK_SYMBOL ||
1388 dStrcasecmp(tval, "url") != 0)
1393 dStrAsciiCasecmp(tval, "url") != 0)
13891394 return NULL;
13901395
13911396 nextToken();
14311436 nextToken();
14321437
14331438 if (ttype == CSS_TK_SYMBOL &&
1434 dStrcasecmp(tval, "url") == 0)
1439 dStrAsciiCasecmp(tval, "url") == 0)
14351440 urlStr = parseUrl();
14361441 else if (ttype == CSS_TK_STRING)
14371442 urlStr = dStrdup (tval);
14431448 mediaSyntaxIsOK = false;
14441449 mediaIsSelected = false;
14451450 while (ttype == CSS_TK_SYMBOL) {
1446 if (dStrcasecmp(tval, "all") == 0 ||
1447 dStrcasecmp(tval, "screen") == 0)
1451 if (dStrAsciiCasecmp(tval, "all") == 0 ||
1452 dStrAsciiCasecmp(tval, "screen") == 0)
14481453 mediaIsSelected = true;
14491454 nextToken();
14501455 if (ttype == CSS_TK_CHAR && tval[0] == ',') {
14851490
14861491 /* parse a comma-separated list of media */
14871492 while (ttype == CSS_TK_SYMBOL) {
1488 if (dStrcasecmp(tval, "all") == 0 ||
1489 dStrcasecmp(tval, "screen") == 0)
1493 if (dStrAsciiCasecmp(tval, "all") == 0 ||
1494 dStrAsciiCasecmp(tval, "screen") == 0)
14901495 mediaIsSelected = true;
14911496 nextToken();
14921497 if (ttype == CSS_TK_CHAR && tval[0] == ',') {
15721577 parser.tval[0] == '@') {
15731578 parser.nextToken();
15741579 if (parser.ttype == CSS_TK_SYMBOL) {
1575 if (dStrcasecmp(parser.tval, "import") == 0 &&
1580 if (dStrAsciiCasecmp(parser.tval, "import") == 0 &&
15761581 html != NULL &&
15771582 importsAreAllowed) {
15781583 parser.parseImport(html, url);
1579 } else if (dStrcasecmp(parser.tval, "media") == 0) {
1584 } else if (dStrAsciiCasecmp(parser.tval, "media") == 0) {
15801585 parser.parseMedia();
15811586 } else {
15821587 parser.ignoreStatement();
189189 {
190190 Decode *dc = NULL;
191191
192 if (format && !dStrcasecmp(format, "chunked")) {
192 if (format && !dStrAsciiCasecmp(format, "chunked")) {
193193 int *chunk_remaining = dNew(int, 1);
194194 *chunk_remaining = 0;
195195 dc = dNew(Decode, 1);
214214 Decode *dc = NULL;
215215
216216 if (format && *format) {
217 if (!dStrcasecmp(format, "gzip") || !dStrcasecmp(format, "x-gzip")) {
217 if (!dStrAsciiCasecmp(format, "gzip") ||
218 !dStrAsciiCasecmp(format, "x-gzip")) {
218219 z_stream *zs;
219220 _MSG("gzipped data!\n");
220221
244245 */
245246 static int Decode_is_ascii(const char *str)
246247 {
247 return (!(dStrcasecmp(str, "ASCII") &&
248 dStrcasecmp(str, "US-ASCII") &&
249 dStrcasecmp(str, "us") &&
250 dStrcasecmp(str, "IBM367") &&
251 dStrcasecmp(str, "cp367") &&
252 dStrcasecmp(str, "csASCII") &&
253 dStrcasecmp(str, "ANSI_X3.4-1968") &&
254 dStrcasecmp(str, "iso-ir-6") &&
255 dStrcasecmp(str, "ANSI_X3.4-1986") &&
256 dStrcasecmp(str, "ISO_646.irv:1991") &&
257 dStrcasecmp(str, "ISO646-US")));
248 return (!(dStrAsciiCasecmp(str, "ASCII") &&
249 dStrAsciiCasecmp(str, "US-ASCII") &&
250 dStrAsciiCasecmp(str, "us") &&
251 dStrAsciiCasecmp(str, "IBM367") &&
252 dStrAsciiCasecmp(str, "cp367") &&
253 dStrAsciiCasecmp(str, "csASCII") &&
254 dStrAsciiCasecmp(str, "ANSI_X3.4-1968") &&
255 dStrAsciiCasecmp(str, "iso-ir-6") &&
256 dStrAsciiCasecmp(str, "ANSI_X3.4-1986") &&
257 dStrAsciiCasecmp(str, "ISO_646.irv:1991") &&
258 dStrAsciiCasecmp(str, "ISO646-US")));
258259 }
259260
260261 /*
270271
271272 if (format &&
272273 strlen(format) &&
273 dStrcasecmp(format,"UTF-8") &&
274 dStrAsciiCasecmp(format,"UTF-8") &&
274275 !Decode_is_ascii(format)) {
275276
276277 iconv_t ic = iconv_open("UTF-8", format);
9393 return Fl_Choice::handle(e);
9494 };
9595 };
96
97 class EnterButton : public Fl_Button {
98 public:
99 EnterButton (int x,int y,int w,int h, const char* label = 0) :
100 Fl_Button (x,y,w,h,label) {};
101 int handle(int e);
102 };
103
104 int EnterButton::handle(int e)
105 {
106 if (e == FL_KEYBOARD && Fl::focus() == this && Fl::event_key() == FL_Enter){
107 set_changed();
108 simulate_key_action();
109 do_callback();
110 return 1;
111 }
112 return Fl_Button::handle(e);
113 }
96114
97115 //----------------------------------------------------------------------------
98116
353371 bw = (ww - gap)/nb - gap;
354372 xpos += gap;
355373 for (int i=1; i <= nb; ++i) {
356 b = new Fl_Button(xpos, wh-bh, bw, bh, txt[i]);
374 b = new EnterButton(xpos, wh-bh, bw, bh, txt[i]);
357375 b->align(FL_ALIGN_WRAP|FL_ALIGN_CLIP);
358376 b->box(FL_UP_BOX);
359377 b->callback(choice5_cb, INT2VOIDP(i));
425443
426444 /* "OK" button */
427445 y += input_h + 20;
428 Fl_Button *ok_button = new Fl_Button(200, y, 50, button_h, "OK");
446 Fl_Button *ok_button = new EnterButton(200, y, 50, button_h, "OK");
429447 ok_button->labelsize(14);
430448 ok_button->callback(Dialog_user_password_cb);
431449 window->add(ok_button);
432450
433451 /* "Cancel" button */
434452 Fl_Button *cancel_button =
435 new Fl_Button(50, y, 100, button_h, "Cancel");
453 new EnterButton(50, y, 100, button_h, "Cancel");
436454 cancel_button->labelsize(14);
437455 cancel_button->callback(Dialog_user_password_cb);
438456 window->add(cancel_button);
0 /*
1 * File: digest.c
2 *
3 * Copyright 2009 Justus Winter <4winter@informatik.uni-hamburg.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 */
10
11 #include <stdlib.h>
12 #include "digest.h"
13 #include "md5.h"
14 #include "msg.h"
15 #include "../dlib/dlib.h"
16
17 static const char *ALGORITHM2STR[] = { NULL, "MD5", "MD5-sess" };
18 static const char *QOP2STR[] = { NULL, "auth", "auth-int" };
19 static const char hexchars[] = "0123456789abcdef";
20
21 static Dstr *md5hexdigest(const Dstr *data)
22 {
23 md5_state_t state;
24 md5_byte_t digest[16];
25 Dstr *result = dStr_sized_new(33);
26 int i;
27
28 md5_init(&state);
29 md5_append(&state, (const md5_byte_t *)data->str, data->len);
30 md5_finish(&state, digest);
31
32 for (i = 0; i < 16; i++)
33 dStr_sprintfa(result, "%02x", digest[i]);
34 return result;
35 }
36
37 /*
38 * Returns a pointer to a newly allocated string containing a cnonce
39 */
40 char *a_Digest_create_cnonce(void)
41 {
42 int i;
43 char *result = dNew(char, 33);
44 for (i = 0; i < 32; i++)
45 result[i] = hexchars[rand() % 16];
46 result[32] = 0;
47 return result;
48 }
49
50 /*
51 * This portion only has to be calculated once.
52 */
53 int a_Digest_compute_digest(AuthRealm_t *realm, const char *username,
54 const char *passwd)
55 {
56 Dstr *a1;
57 Dstr *digest;
58
59 if (realm->algorithm == MD5 || realm->algorithm == ALGORITHMNOTSET) {
60 /* A1 = unq(username-value) ":" unq(realm-value) ":" passwd */
61 a1 = dStr_new(NULL);
62 dStr_sprintf(a1, "%s:%s:%s", username, realm->name, passwd);
63 } else if (realm->algorithm == MD5SESS) {
64 /* A1 = H( unq(username-value) ":" unq(realm-value)
65 ** ":" passwd )
66 ** ":" unq(nonce-value) ":" unq(cnonce-value)
67 */
68 Dstr *a0 = dStr_new(NULL);
69 dStr_sprintf(a0, "%s:%s:%s", username, realm->name, passwd);
70 Dstr *ha0 = md5hexdigest(a0);
71 a1 = dStr_new(NULL);
72 dStr_sprintf(a1, "%s:%s:%s", ha0, realm->nonce, realm->cnonce);
73 dStr_free(a0, 1);
74 dStr_free(ha0, 1);
75 } else {
76 MSG("a_Digest_create_auth: Unknown algorithm.\n");
77 return 0;
78 }
79
80 digest = md5hexdigest(a1);
81 realm->authorization = digest->str;
82 dStr_shred(a1);
83 dStr_free(a1, 1);
84 dStr_free(digest, 0);
85 return 1;
86 }
87
88 /*
89 * This portion is calculatd for each request.
90 */
91 static Dstr *Digest_create_response(AuthRealm_t *realm, const char *method,
92 const char *digest_uri,
93 const Dstr *entity_body)
94 {
95 Dstr *ha2;
96 Dstr *result;
97
98 if (realm->qop == QOPNOTSET || realm->qop == AUTH) {
99 /* A2 = Method ":" digest-uri-value */
100 Dstr *a2 = dStr_new(NULL);
101 dStr_sprintf(a2, "%s:%s", method, digest_uri);
102 ha2 = md5hexdigest(a2);
103 dStr_free(a2, 1);
104 } else if (realm->qop == AUTHINT) {
105 /* A2 = Method ":" digest-uri-value ":" H(entity-body) */
106 Dstr *hentity = md5hexdigest(entity_body);
107 Dstr *a2 = dStr_new(NULL);
108 dStr_sprintf(a2, "%s:%s:%s", method, digest_uri, hentity->str);
109 ha2 = md5hexdigest(a2);
110 dStr_free(hentity, 1);
111 dStr_free(a2, 1);
112 } else {
113 MSG("a_Digest_create_auth: Unknown qop value.\n");
114 return NULL;
115 }
116 result = dStr_new(NULL);
117
118 if (realm->qop == AUTH || realm->qop == AUTHINT) {
119 dStr_sprintf(result,
120 "%s:%s:%08x:%s:%s:%s",
121 realm->authorization,
122 realm->nonce,
123 realm->nonce_count,
124 realm->cnonce,
125 QOP2STR[realm->qop],
126 ha2->str);
127 } else {
128 dStr_sprintf(result,
129 "%s:%s:%s",
130 realm->authorization,
131 realm->nonce,
132 ha2->str);
133 }
134
135 Dstr *request_digest = md5hexdigest(result);
136 dStr_free(result, 1);
137 dStr_free(ha2, 1);
138 return request_digest;
139 }
140
141 static void Digest_Dstr_append_token_value(Dstr *str, int delimiter,
142 const char *token,
143 const char *value, int quoted)
144 {
145 char c;
146 dStr_sprintfa(str, "%s%s=", (delimiter ? ", " : ""), token);
147 if (quoted) {
148 dStr_append_c(str, '"');
149 while ((c = *value++)) {
150 if (c == '"')
151 dStr_append_c(str, '\\');
152 dStr_append_c(str, c);
153 }
154 dStr_append_c(str, '"');
155 } else {
156 dStr_append(str, value);
157 }
158 }
159
160 /*
161 * Construct Digest Authorization header.
162 *
163 * Field ordering: furaisanjin reports that his DVD recorder requires the
164 * order that IE happens to use: "username, realm, nonce, uri, cnonce, nc,
165 * algorithm, response, qop". It apparently doesn't use "opaque", so that's
166 * been left where it already was.
167 */
168 char *a_Digest_authorization_hdr(AuthRealm_t *realm, const DilloUrl *url,
169 const char *digest_uri)
170 {
171 char *ret;
172 Dstr *response, *result;
173 const char *method = URL_FLAGS(url) & URL_Post ? "POST" : "GET";
174
175 realm->nonce_count++;
176 response = Digest_create_response(realm, method, digest_uri, URL_DATA(url));
177 if (!response)
178 return NULL;
179 result = dStr_new("Authorization: Digest ");
180 Digest_Dstr_append_token_value(result, 0, "username", realm->username, 1);
181 Digest_Dstr_append_token_value(result, 1, "realm", realm->name, 1);
182 Digest_Dstr_append_token_value(result, 1, "nonce", realm->nonce, 1);
183 Digest_Dstr_append_token_value(result, 1, "uri", digest_uri, 1);
184 if (realm->qop != QOPNOTSET) {
185 Digest_Dstr_append_token_value(result, 1, "cnonce", realm->cnonce, 1);
186 dStr_sprintfa(result, ", nc=%08x", realm->nonce_count);
187 }
188 if (realm->algorithm != ALGORITHMNOTSET) {
189 Digest_Dstr_append_token_value(result, 1, "algorithm",
190 ALGORITHM2STR[realm->algorithm], 0);
191 }
192 Digest_Dstr_append_token_value(result, 1, "response", response->str, 1);
193 if (realm->opaque)
194 Digest_Dstr_append_token_value(result, 1, "opaque", realm->opaque, 1);
195 if (realm->qop != QOPNOTSET)
196 Digest_Dstr_append_token_value(result, 1, "qop", QOP2STR[realm->qop], 1);
197 dStr_sprintfa(result, "\r\n");
198
199 dStr_free(response, 1);
200 ret = result->str;
201 dStr_free(result, 0);
202 return ret;
203 }
0 #ifndef __DIGEST_H__
1 #define __DIGEST_H__
2
3 #include "auth.h"
4 #include "../dlib/dlib.h"
5
6
7 char *a_Digest_create_cnonce(void);
8 int a_Digest_compute_digest(AuthRealm_t *realm,
9 const char *username,
10 const char *passwd);
11 char *a_Digest_authorization_hdr(AuthRealm_t *realm,
12 const DilloUrl *url,
13 const char *uri);
14
15 #endif /* !__DIGEST_H__ */
409409
410410 if (idx == argc) {
411411 /* No URLs/files on cmdline. Send startup screen */
412 if (strcmp(URL_STR(prefs.start_page), "about:blank") == 0)
412 if (dStrAsciiCasecmp(URL_SCHEME(prefs.start_page), "about") == 0 &&
413 strcmp(URL_PATH(prefs.start_page), "blank") == 0)
413414 a_UIcmd_open_url(bw, NULL);
414415 else
415416 a_UIcmd_open_url(bw, prefs.start_page);
112112 int i;
113113
114114 for (i = 0; i < dns_queue_size; i++)
115 if (!strcmp(hostname, dns_queue[i].hostname))
115 if (!dStrAsciiCasecmp(hostname, dns_queue[i].hostname))
116116 return i;
117117
118118 return -1;
376376
377377 /* check for cache hit. */
378378 for (i = 0; i < dns_cache_size; i++)
379 if (!strcmp(hostname, dns_cache[i].hostname))
379 if (!dStrAsciiCasecmp(hostname, dns_cache[i].hostname))
380380 break;
381381
382382 if (i < dns_cache_size) {
444444 * with the same hostname*/
445445 for (j = i; j < dns_queue_size; j++)
446446 if (dns_queue[j].channel == -2 &&
447 !strcmp(dns_queue[j].hostname, dns_queue[i].hostname))
447 !dStrAsciiCasecmp(dns_queue[j].hostname,
448 dns_queue[i].hostname)) {
448449 dns_queue[j].channel = ch;
450 }
449451 Dns_server_req(ch, dns_queue[i].hostname);
450452 } else
451453 return;
270270 for (int idx = 0; idx < inputs->size(); idx++) {
271271 DilloHtmlInput *input = inputs->get(idx);
272272 if (input->type == DILLO_HTML_INPUT_RADIO &&
273 input->name && !dStrcasecmp(input->name, name))
273 input->name && !dStrAsciiCasecmp(input->name, name))
274274 return input;
275275 }
276276 }
317317
318318 method = DILLO_HTML_METHOD_GET;
319319 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "method"))) {
320 if (!dStrcasecmp(attrbuf, "post")) {
320 if (!dStrAsciiCasecmp(attrbuf, "post")) {
321321 method = DILLO_HTML_METHOD_POST;
322 } else if (dStrcasecmp(attrbuf, "get")) {
322 } else if (dStrAsciiCasecmp(attrbuf, "get")) {
323323 BUG_MSG("Unknown form submission method \"%s\"\n", attrbuf);
324324 }
325325 }
332332 content_type = DILLO_HTML_ENC_URLENCODED;
333333 if ((method == DILLO_HTML_METHOD_POST) &&
334334 ((attrbuf = a_Html_get_attr(html, tag, tagsize, "enctype")))) {
335 if (!dStrcasecmp(attrbuf, "multipart/form-data"))
335 if (!dStrAsciiCasecmp(attrbuf, "multipart/form-data"))
336336 content_type = DILLO_HTML_ENC_MULTIPART;
337337 }
338338 charset = NULL;
342342 char *ptr = first = dStrdup(attrbuf);
343343 while (ptr && !charset) {
344344 char *curr = dStrsep(&ptr, " ,");
345 if (!dStrcasecmp(curr, "utf-8")) {
345 if (!dStrAsciiCasecmp(curr, "utf-8")) {
346346 charset = curr;
347 } else if (!dStrcasecmp(curr, "UNKNOWN")) {
347 } else if (!dStrAsciiCasecmp(curr, "UNKNOWN")) {
348348 /* defined to be whatever encoding the document is in */
349349 charset = html->charset;
350350 }
440440
441441 init_str = NULL;
442442 inp_type = DILLO_HTML_INPUT_UNKNOWN;
443 if (!dStrcasecmp(type, "password")) {
443 if (!dStrAsciiCasecmp(type, "password")) {
444444 inp_type = DILLO_HTML_INPUT_PASSWORD;
445445 attrbuf = a_Html_get_attr(html, tag, tagsize, "size");
446446 int size = Html_input_get_size(html, attrbuf);
447447 resource = factory->createEntryResource (size, true, NULL);
448448 init_str = value;
449 } else if (!dStrcasecmp(type, "checkbox")) {
449 } else if (!dStrAsciiCasecmp(type, "checkbox")) {
450450 inp_type = DILLO_HTML_INPUT_CHECKBOX;
451451 resource = factory->createCheckButtonResource(false);
452452 init_val = (a_Html_get_attr(html, tag, tagsize, "checked") != NULL);
453453 init_str = (value) ? value : dStrdup("on");
454 } else if (!dStrcasecmp(type, "radio")) {
454 } else if (!dStrAsciiCasecmp(type, "radio")) {
455455 inp_type = DILLO_HTML_INPUT_RADIO;
456456 RadioButtonResource *rb_r = NULL;
457457 DilloHtmlInput *input = Html_get_radio_input(html, name);
460460 resource = factory->createRadioButtonResource(rb_r, false);
461461 init_val = (a_Html_get_attr(html, tag, tagsize, "checked") != NULL);
462462 init_str = value;
463 } else if (!dStrcasecmp(type, "hidden")) {
463 } else if (!dStrAsciiCasecmp(type, "hidden")) {
464464 inp_type = DILLO_HTML_INPUT_HIDDEN;
465465 init_str = value;
466466 int size = Html_input_get_size(html, NULL);
467467 resource = factory->createEntryResource(size, false, name);
468 } else if (!dStrcasecmp(type, "submit")) {
468 } else if (!dStrAsciiCasecmp(type, "submit")) {
469469 inp_type = DILLO_HTML_INPUT_SUBMIT;
470470 init_str = (value) ? value : dStrdup("submit");
471471 resource = factory->createLabelButtonResource(init_str);
472472 // gtk_widget_set_sensitive(widget, FALSE); /* Until end of FORM! */
473 } else if (!dStrcasecmp(type, "reset")) {
473 } else if (!dStrAsciiCasecmp(type, "reset")) {
474474 inp_type = DILLO_HTML_INPUT_RESET;
475475 init_str = (value) ? value : dStrdup("Reset");
476476 resource = factory->createLabelButtonResource(init_str);
477477 // gtk_widget_set_sensitive(widget, FALSE); /* Until end of FORM! */
478 } else if (!dStrcasecmp(type, "image")) {
478 } else if (!dStrAsciiCasecmp(type, "image")) {
479479 if (URL_FLAGS(html->base_url) & URL_SpamSafe) {
480480 /* Don't request the image; make a text submit button instead */
481481 inp_type = DILLO_HTML_INPUT_SUBMIT;
490490 embed = Html_input_image(html, tag, tagsize);
491491 init_str = value;
492492 }
493 } else if (!dStrcasecmp(type, "file")) {
493 } else if (!dStrAsciiCasecmp(type, "file")) {
494494 bool valid = true;
495495 if (html->InFlags & IN_FORM) {
496496 DilloHtmlForm *form = html->getCurrentForm();
511511 init_str = dStrdup("File selector");
512512 resource = factory->createLabelButtonResource(init_str);
513513 }
514 } else if (!dStrcasecmp(type, "button")) {
514 } else if (!dStrAsciiCasecmp(type, "button")) {
515515 inp_type = DILLO_HTML_INPUT_BUTTON;
516516 if (value) {
517517 init_str = value;
518518 resource = factory->createLabelButtonResource(init_str);
519519 }
520 } else if (!dStrcasecmp(type, "text") || !*type) {
520 } else {
521521 /* Text input, which also is the default */
522522 inp_type = DILLO_HTML_INPUT_TEXT;
523 if (*type && dStrAsciiCasecmp(type, "text"))
524 BUG_MSG("Unknown input type: \"%s\"\n", type);
523525 attrbuf = a_Html_get_attr(html, tag, tagsize, "size");
524526 int size = Html_input_get_size(html, attrbuf);
525527 resource = factory->createEntryResource(size, false, NULL);
526528 init_str = value;
527 } else {
528 /* Unknown input type */
529 BUG_MSG("Unknown input type: \"%s\"\n", type);
530 }
531
529 }
532530 if (resource)
533531 embed = new Embed (resource);
534532
832830
833831 type = a_Html_get_attr_wdef(html, tag, tagsize, "type", "");
834832
835 if (!dStrcasecmp(type, "button")) {
833 if (!dStrAsciiCasecmp(type, "button")) {
836834 inp_type = DILLO_HTML_INPUT_BUTTON;
837 } else if (!dStrcasecmp(type, "reset")) {
835 } else if (!dStrAsciiCasecmp(type, "reset")) {
838836 inp_type = DILLO_HTML_INPUT_BUTTON_RESET;
839 } else if (!dStrcasecmp(type, "submit") || !*type) {
837 } else if (!dStrAsciiCasecmp(type, "submit") || !*type) {
840838 /* submit button is the default */
841839 inp_type = DILLO_HTML_INPUT_BUTTON_SUBMIT;
842840 } else {
10351033 char *boundary = NULL;
10361034 iconv_t char_encoder = (iconv_t) -1;
10371035
1038 if (submit_charset && dStrcasecmp(submit_charset, "UTF-8")) {
1036 if (submit_charset && dStrAsciiCasecmp(submit_charset, "UTF-8")) {
10391037 char_encoder = iconv_open(submit_charset, "UTF-8");
10401038 if (char_encoder == (iconv_t) -1) {
10411039 MSG_WARN("Cannot convert to character encoding '%s'\n",
13091307 (void)a_Misc_get_content_type_from_data(file->str, file->len, &ctype);
13101308 /* Heuristic: text/plain with ".htm[l]" extension -> text/html */
13111309 if ((ext = strrchr(filename, '.')) &&
1312 !dStrcasecmp(ctype, "text/plain") &&
1313 (!dStrcasecmp(ext, ".html") || !dStrcasecmp(ext, ".htm"))) {
1310 !dStrAsciiCasecmp(ctype, "text/plain") &&
1311 (!dStrAsciiCasecmp(ext, ".html") || !dStrAsciiCasecmp(ext, ".htm"))){
13141312 ctype = "text/html";
13151313 }
13161314
14751473 for (int idx = 0; idx < inputs->size(); idx++) {
14761474 DilloHtmlInput *input = inputs->get(idx);
14771475 if (input->type == DILLO_HTML_INPUT_RADIO &&
1478 input->name && !dStrcasecmp(input->name, name))
1476 input->name && !dStrAsciiCasecmp(input->name, name))
14791477 return input;
14801478 }
14811479 return NULL;
1515 /*-----------------------------------------------------------------------------
1616 * Includes
1717 *---------------------------------------------------------------------------*/
18 #include <ctype.h> /* for isspace and tolower */
18 #include <ctype.h> /* for isspace */
1919 #include <string.h> /* for memcpy and memmove */
2020 #include <stdlib.h>
2121 #include <stdio.h> /* for sprintf */
310310 if ((align = a_Html_get_attr(html, tag, tagsize, "align"))) {
311311 TextAlignType textAlignType = TEXT_ALIGN_LEFT;
312312
313 if (dStrcasecmp (align, "left") == 0)
313 if (dStrAsciiCasecmp (align, "left") == 0)
314314 textAlignType = TEXT_ALIGN_LEFT;
315 else if (dStrcasecmp (align, "right") == 0)
315 else if (dStrAsciiCasecmp (align, "right") == 0)
316316 textAlignType = TEXT_ALIGN_RIGHT;
317 else if (dStrcasecmp (align, "center") == 0)
317 else if (dStrAsciiCasecmp (align, "center") == 0)
318318 textAlignType = TEXT_ALIGN_CENTER;
319 else if (dStrcasecmp (align, "justify") == 0)
319 else if (dStrAsciiCasecmp (align, "justify") == 0)
320320 textAlignType = TEXT_ALIGN_JUSTIFY;
321321 #if 0
322 else if (dStrcasecmp (align, "char") == 0) {
322 else if (dStrAsciiCasecmp (align, "char") == 0) {
323323 /* TODO: Actually not supported for <p> etc. */
324324 v.textAlign = TEXT_ALIGN_STRING;
325325 if ((charattr = a_Html_get_attr(html, tag, tagsize, "char"))) {
351351 VAlignType valign;
352352
353353 if ((attr = a_Html_get_attr(html, tag, tagsize, "valign"))) {
354 if (dStrcasecmp (attr, "top") == 0)
354 if (dStrAsciiCasecmp (attr, "top") == 0)
355355 valign = VALIGN_TOP;
356 else if (dStrcasecmp (attr, "bottom") == 0)
356 else if (dStrAsciiCasecmp (attr, "bottom") == 0)
357357 valign = VALIGN_BOTTOM;
358 else if (dStrcasecmp (attr, "baseline") == 0)
358 else if (dStrAsciiCasecmp (attr, "baseline") == 0)
359359 valign = VALIGN_BASELINE;
360360 else
361361 valign = VALIGN_MIDDLE;
11061106 }
11071107
11081108 if (spaceCnt) {
1109 // add break possibility for the white-space:pre-wrap case
1110 HT2TB(html)->addBreakOption (html->styleEngine->wordStyle ());
11091111 spc = dStrnfill(spaceCnt, ' ');
11101112 HT2TB(html)->addText (spc, spaceCnt, html->styleEngine->wordStyle ());
11111113 dFree(spc);
12071209 Html_process_space(html, word2 + start, i - start);
12081210 } else if (!strncmp(word2+i, utf8_zero_width_space, 3)) {
12091211 i += 3;
1212 HT2TB(html)->addBreakOption(html->styleEngine->wordStyle ());
12101213 } else if (a_Utf8_ideographic(word2+i, beyond_word2, &len)) {
12111214 i += len;
12121215 HT2TB(html)->addText(word2 + start, i - start,
12131216 html->styleEngine->wordStyle ());
1217 HT2TB(html)->addBreakOption(html->styleEngine->wordStyle ());
12141218 } else {
12151219 do {
12161220 i += len;
12351239 int i;
12361240
12371241 for (i = 0; i < tagsize && tagstr[i] != '\0'; i++) {
1238 if (tolower(tagstr[i]) != tolower(tag[i]))
1242 if (D_ASCII_TOLOWER(tagstr[i]) != D_ASCII_TOLOWER(tag[i]))
12391243 return false;
12401244 }
12411245 /* The test for '/' is for xml compatibility: "empty/>" will be matched. */
14571461 int i;
14581462
14591463 for (i = 0; val[i]; ++i)
1460 if (!(isalnum(val[i]) || strchr(":_.-", val[i])))
1464 if (!isascii(val[i]) || !(isalnum(val[i]) || strchr(":_.-", val[i])))
14611465 break;
14621466
1463 if (val[i] || !isalpha(val[0]))
1467 if (val[i] || !(isascii(val[0]) && isalpha(val[0])))
14641468 BUG_MSG("'%s' value is not of the form "
14651469 "[A-Za-z][A-Za-z0-9:_.-]*\n", attrname);
14661470
15251529 _MSG("New: {%s}\n", ntag);
15261530
15271531 /* The default DT_NONE type is TagSoup */
1528 if (!dStrncasecmp(ntag, HTML_SGML_sig, strlen(HTML_SGML_sig))) {
1532 if (!dStrnAsciiCasecmp(ntag, HTML_SGML_sig, strlen(HTML_SGML_sig))) {
15291533 p = ntag + strlen(HTML_SGML_sig) + 1;
15301534 if (!strncmp(p, HTML401, strlen(HTML401)) &&
1531 dStristr(p + strlen(HTML401), HTML401_url)) {
1535 dStriAsciiStr(p + strlen(HTML401), HTML401_url)) {
15321536 html->DocType = DT_HTML;
15331537 html->DocTypeVersion = 4.01f;
15341538 } else if (!strncmp(p, XHTML1, strlen(XHTML1)) &&
1535 dStristr(p + strlen(XHTML1), XHTML1_url)) {
1539 dStriAsciiStr(p + strlen(XHTML1), XHTML1_url)) {
15361540 html->DocType = DT_XHTML;
15371541 html->DocTypeVersion = 1.0f;
15381542 } else if (!strncmp(p, XHTML11, strlen(XHTML11)) &&
1539 dStristr(p + strlen(XHTML11), XHTML11_url)) {
1543 dStriAsciiStr(p + strlen(XHTML11), XHTML11_url)) {
15401544 html->DocType = DT_XHTML;
15411545 html->DocTypeVersion = 1.1f;
15421546 } else if (!strncmp(p, HTML40, strlen(HTML40))) {
15491553 html->DocType = DT_HTML;
15501554 html->DocTypeVersion = 2.0f;
15511555 }
1552 } else if (!dStrcasecmp(ntag, HTML5_sig)) {
1556 } else if (!dStrAsciiCasecmp(ntag, HTML5_sig)) {
15531557 BUG_MSG("Document follows HTML5 working draft; treating as HTML4.\n");
15541558 html->DocType = DT_HTML;
15551559 html->DocTypeVersion = 5.0f;
16821686
16831687 if (!(attrbuf = a_Html_get_attr(html, tag, tagsize, "type"))) {
16841688 BUG_MSG("type attribute is required for <style>\n");
1685 } else if (dStrcasecmp(attrbuf, "text/css")) {
1689 } else if (dStrAsciiCasecmp(attrbuf, "text/css")) {
16861690 html->loadCssFromStash = false;
16871691 }
16881692 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "media")) &&
1689 dStrcasecmp(attrbuf, "all") && !dStristr(attrbuf, "screen")) {
1693 dStrAsciiCasecmp(attrbuf, "all") && !dStriAsciiStr(attrbuf, "screen")) {
16901694 /* HTML 4.01 sec. 6.13 says that media descriptors are case-sensitive,
16911695 * but sec. 14.2.3 says that the attribute is case-insensitive.
16921696 * TODO can be a comma-separated list.
18551859 textblock->addWidget(bullet, html->styleEngine->wordStyle ());
18561860 textblock->addSpace(html->styleEngine->wordStyle ());
18571861
1858 if (tolower(tag[1]) == 'i') {
1862 if (D_ASCII_TOLOWER(tag[1]) == 'i') {
18591863 /* IFRAME usually comes with very long advertising/spying URLS,
18601864 * to not break rendering we will force name="IFRAME" */
18611865 textblock->addText ("IFRAME", html->styleEngine->wordStyle ());
21152119 Image->bg_color = HT2TB(html)->getBgColor()->getColor();
21162120
21172121 load_now = prefs.load_images ||
2118 !dStrcasecmp(URL_SCHEME(url), "data") ||
2122 !dStrAsciiCasecmp(URL_SCHEME(url), "data") ||
21192123 (a_Capi_get_flags_with_redirection(url) & CAPI_IsCached);
21202124 bool loading = false;
21212125 if (load_now)
22872291 }
22882292 attrbuf = a_Html_get_attr(html, tag, tagsize, "shape");
22892293
2290 if (!attrbuf || !*attrbuf || !dStrcasecmp(attrbuf, "rect")) {
2294 if (!attrbuf || !*attrbuf || !dStrAsciiCasecmp(attrbuf, "rect")) {
22912295 /* the default shape is a rectangle */
22922296 type = RECTANGLE;
2293 } else if (dStrcasecmp(attrbuf, "default") == 0) {
2297 } else if (dStrAsciiCasecmp(attrbuf, "default") == 0) {
22942298 /* "default" is the background */
22952299 type = BACKGROUND;
2296 } else if (dStrcasecmp(attrbuf, "circle") == 0) {
2300 } else if (dStrAsciiCasecmp(attrbuf, "circle") == 0) {
22972301 type = CIRCLE;
2298 } else if (dStrncasecmp(attrbuf, "poly", 4) == 0) {
2302 } else if (dStrnAsciiCasecmp(attrbuf, "poly", 4) == 0) {
22992303 type = POLYGON;
23002304 } else {
23012305 BUG_MSG("<area> unknown shape: \"%s\"\n", attrbuf);
23892393 char ch, *p1, *p2;
23902394 Dstr *Buf = html->attr_data;
23912395
2392 if (dStrncasecmp("javascript", Buf->str, 10) == 0) {
2396 if (dStrnAsciiCasecmp("javascript", Buf->str, 10) == 0) {
23932397 i = strcspn(Buf->str, "'\"");
23942398 ch = Buf->str[i];
23952399 if ((ch == '"' || ch == '\'') &&
24352439
24362440 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "href"))) {
24372441 /* if it's a javascript link, extract the reference. */
2438 if (tolower(attrbuf[0]) == 'j')
2442 if (D_ASCII_TOLOWER(attrbuf[0]) == 'j')
24392443 attrbuf = Html_get_javascript_link(html);
24402444
24412445 url = a_Html_url_new(html, attrbuf, NULL, 0);
25432547 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "type"))) {
25442548
25452549 /* list_style_type explicitly defined */
2546 if (dStrcasecmp(attrbuf, "disc") == 0)
2550 if (dStrAsciiCasecmp(attrbuf, "disc") == 0)
25472551 list_style_type = LIST_STYLE_TYPE_DISC;
2548 else if (dStrcasecmp(attrbuf, "circle") == 0)
2552 else if (dStrAsciiCasecmp(attrbuf, "circle") == 0)
25492553 list_style_type = LIST_STYLE_TYPE_CIRCLE;
2550 else if (dStrcasecmp(attrbuf, "square") == 0)
2554 else if (dStrAsciiCasecmp(attrbuf, "square") == 0)
25512555 list_style_type = LIST_STYLE_TYPE_SQUARE;
25522556 else
25532557 /* invalid value */
28482852 }
28492853
28502854 if ((equiv = a_Html_get_attr(html, tag, tagsize, "http-equiv"))) {
2851 if (!dStrcasecmp(equiv, "refresh") &&
2855 if (!dStrAsciiCasecmp(equiv, "refresh") &&
28522856 (content = a_Html_get_attr(html, tag, tagsize, "content"))) {
28532857
28542858 /* Get delay, if present, and make a message with it */
29002904 a_Url_free(new_url);
29012905 dFree(mr_url);
29022906
2903 } else if (!dStrcasecmp(equiv, "content-type") &&
2907 } else if (!dStrAsciiCasecmp(equiv, "content-type") &&
29042908 (content = a_Html_get_attr(html, tag, tagsize, "content"))) {
29052909 _MSG("Html_tag_open_meta: content={%s}\n", content);
29062910 /* Cannot ask cache whether the content type was changed, as
30053009 dReturn_if_fail (prefs.load_stylesheets);
30063010 /* CSS stylesheet link */
30073011 if (!(attrbuf = a_Html_get_attr(html, tag, tagsize, "rel")) ||
3008 dStrcasecmp(attrbuf, "stylesheet"))
3012 dStrAsciiCasecmp(attrbuf, "stylesheet"))
30093013 return;
30103014
30113015 /* IMPLIED attributes? */
30123016 if (((attrbuf = a_Html_get_attr(html, tag, tagsize, "type")) &&
3013 dStrcasecmp(attrbuf, "text/css")) ||
3017 dStrAsciiCasecmp(attrbuf, "text/css")) ||
30143018 ((attrbuf = a_Html_get_attr(html, tag, tagsize, "media")) &&
3015 !dStristr(attrbuf, "screen") && dStrcasecmp(attrbuf, "all")))
3019 !dStriAsciiStr(attrbuf, "screen") && dStrAsciiCasecmp(attrbuf, "all")))
30163020 return;
30173021
30183022 if (!(attrbuf = a_Html_get_attr(html, tag, tagsize, "href")) ||
32263230 static int Html_tag_compare(const char *p1, const char *p2)
32273231 {
32283232 while ( *p2 ) {
3229 if (tolower(*p1) != *p2)
3230 return(tolower(*p1) - *p2);
3233 if (D_ASCII_TOLOWER(*p1) != *p2)
3234 return(D_ASCII_TOLOWER(*p1) - *p2);
32313235 ++p1;
32323236 ++p2;
32333237 }
34693473 if (ni == -1) {
34703474 /* TODO: doctype parsing is a bit fuzzy, but enough for the time being */
34713475 if (!(html->InFlags & IN_HTML)) {
3472 if (tagsize > 9 && !dStrncasecmp(tag, "<!doctype", 9))
3476 if (tagsize > 9 && !dStrnAsciiCasecmp(tag, "<!doctype", 9))
34733477 Html_parse_doctype(html, tag, tagsize);
34743478 }
34753479 /* Ignore unknown tags */
35863590 (tag[i] == '=' || isspace(tag[i]) || tag[i] == '>')))) {
35873591 state = SEEK_TOKEN_START;
35883592 --i;
3589 } else if (tolower(tag[i]) != tolower(attrname[attr_pos++]))
3590 state = SEEK_ATTR_START;
3593 } else {
3594 if (D_ASCII_TOLOWER(tag[i]) != D_ASCII_TOLOWER(attrname[attr_pos]))
3595 state = SEEK_ATTR_START;
3596 attr_pos++;
3597 }
35913598 break;
35923599
35933600 case SEEK_TOKEN_START:
102102 { "new-tab" , KEYS_NEW_TAB , FL_CTRL , 't' },
103103 { "left-tab" , KEYS_LEFT_TAB , FL_CTRL |
104104 FL_SHIFT , FL_Tab },
105 { "left-tab" , KEYS_LEFT_TAB , FL_CTRL , FL_Page_Up },
105106 { "right-tab" , KEYS_RIGHT_TAB , FL_CTRL , FL_Tab },
107 { "right-tab" , KEYS_RIGHT_TAB , FL_CTRL , FL_Page_Down },
106108 { "close-tab" , KEYS_CLOSE_TAB , FL_CTRL , 'w' },
107109 { "find" , KEYS_FIND , FL_CTRL , 'f' },
108110 { "websearch" , KEYS_WEBSEARCH , FL_CTRL , 's' },
242244 {
243245 uint_t i;
244246 for (i = 0; i < sizeof(keyNames) / sizeof(Mapping_t); i++) {
245 if (!dStrcasecmp(keyNames[i].name, keyName)) {
247 if (!dStrAsciiCasecmp(keyNames[i].name, keyName)) {
246248 return keyNames[i].value;
247249 }
248250 }
259261 uint_t i;
260262
261263 for (i = 0; i < sizeof(default_keys) / sizeof(KeyBinding_t); i++) {
262 if (!dStrcasecmp(default_keys[i].name, commandName))
264 if (!dStrAsciiCasecmp(default_keys[i].name, commandName))
263265 return default_keys[i].cmd;
264266 }
265267 return KEYS_INVALID;
273275 {
274276 uint_t i;
275277 for (i = 0; i < sizeof(modifierNames) / sizeof(Mapping_t); i++) {
276 if (!dStrcasecmp(modifierNames[i].name, modifierName)) {
278 if (!dStrAsciiCasecmp(modifierNames[i].name, modifierName)) {
277279 return modifierNames[i].value;
278280 }
279281 }
3939
4040 # "left-tab" and "right-tab" switch to the left/right of the current tab.
4141 # <ctrl><shift>tab = left-tab
42 # <ctrl>PageUp = left-tab
4243 # <ctrl>tab = right-tab
44 # <ctrl>PageDown = right-tab
4345
4446 # "back" and "forward" move back/forward through the browser history.
4547 #backspace = back
0 /*
1 * md5.c was taken from "RFC1321-based (RSA-free) MD5 library" by L. Peter
2 * Deutsch at http://sourceforge.net/projects/libmd5-rfc/ in October 2011.
3 *
4 * The code was not modified when integrated into the Dillo project, but you
5 * should check the source repository to be sure that there have not been
6 * modifications since this notice.
7 */
8
9 /*
10 Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
11
12 This software is provided 'as-is', without any express or implied
13 warranty. In no event will the authors be held liable for any damages
14 arising from the use of this software.
15
16 Permission is granted to anyone to use this software for any purpose,
17 including commercial applications, and to alter it and redistribute it
18 freely, subject to the following restrictions:
19
20 1. The origin of this software must not be misrepresented; you must not
21 claim that you wrote the original software. If you use this software
22 in a product, an acknowledgment in the product documentation would be
23 appreciated but is not required.
24 2. Altered source versions must be plainly marked as such, and must not be
25 misrepresented as being the original software.
26 3. This notice may not be removed or altered from any source distribution.
27
28 L. Peter Deutsch
29 ghost@aladdin.com
30
31 */
32 /* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
33 /*
34 Independent implementation of MD5 (RFC 1321).
35
36 This code implements the MD5 Algorithm defined in RFC 1321, whose
37 text is available at
38 http://www.ietf.org/rfc/rfc1321.txt
39 The code is derived from the text of the RFC, including the test suite
40 (section A.5) but excluding the rest of Appendix A. It does not include
41 any code or documentation that is identified in the RFC as being
42 copyrighted.
43
44 The original and principal author of md5.c is L. Peter Deutsch
45 <ghost@aladdin.com>. Other authors are noted in the change history
46 that follows (in reverse chronological order):
47
48 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
49 either statically or dynamically; added missing #include <string.h>
50 in library.
51 2002-03-11 lpd Corrected argument list for main(), and added int return
52 type, in test program and T value program.
53 2002-02-21 lpd Added missing #include <stdio.h> in test program.
54 2000-07-03 lpd Patched to eliminate warnings about "constant is
55 unsigned in ANSI C, signed in traditional"; made test program
56 self-checking.
57 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
58 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
59 1999-05-03 lpd Original version.
60 */
61
62 #include "md5.h"
63 #include <string.h>
64
65 #undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
66 #ifdef ARCH_IS_BIG_ENDIAN
67 # define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
68 #else
69 # define BYTE_ORDER 0
70 #endif
71
72 #define T_MASK ((md5_word_t)~0)
73 #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
74 #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
75 #define T3 0x242070db
76 #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
77 #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
78 #define T6 0x4787c62a
79 #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
80 #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
81 #define T9 0x698098d8
82 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
83 #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
84 #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
85 #define T13 0x6b901122
86 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
87 #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
88 #define T16 0x49b40821
89 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
90 #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
91 #define T19 0x265e5a51
92 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
93 #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
94 #define T22 0x02441453
95 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
96 #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
97 #define T25 0x21e1cde6
98 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
99 #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
100 #define T28 0x455a14ed
101 #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
102 #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
103 #define T31 0x676f02d9
104 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
105 #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
106 #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
107 #define T35 0x6d9d6122
108 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
109 #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
110 #define T38 0x4bdecfa9
111 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
112 #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
113 #define T41 0x289b7ec6
114 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
115 #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
116 #define T44 0x04881d05
117 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
118 #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
119 #define T47 0x1fa27cf8
120 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
121 #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
122 #define T50 0x432aff97
123 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
124 #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
125 #define T53 0x655b59c3
126 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
127 #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
128 #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
129 #define T57 0x6fa87e4f
130 #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
131 #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
132 #define T60 0x4e0811a1
133 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
134 #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
135 #define T63 0x2ad7d2bb
136 #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
137
138
139 static void
140 md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
141 {
142 md5_word_t
143 a = pms->abcd[0], b = pms->abcd[1],
144 c = pms->abcd[2], d = pms->abcd[3];
145 md5_word_t t;
146 #if BYTE_ORDER > 0
147 /* Define storage only for big-endian CPUs. */
148 md5_word_t X[16];
149 #else
150 /* Define storage for little-endian or both types of CPUs. */
151 md5_word_t xbuf[16];
152 const md5_word_t *X;
153 #endif
154
155 {
156 #if BYTE_ORDER == 0
157 /*
158 * Determine dynamically whether this is a big-endian or
159 * little-endian machine, since we can use a more efficient
160 * algorithm on the latter.
161 */
162 static const int w = 1;
163
164 if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
165 #endif
166 #if BYTE_ORDER <= 0 /* little-endian */
167 {
168 /*
169 * On little-endian machines, we can process properly aligned
170 * data without copying it.
171 */
172 if (!((data - (const md5_byte_t *)0) & 3)) {
173 /* data are properly aligned */
174 X = (const md5_word_t *)data;
175 } else {
176 /* not aligned */
177 memcpy(xbuf, data, 64);
178 X = xbuf;
179 }
180 }
181 #endif
182 #if BYTE_ORDER == 0
183 else /* dynamic big-endian */
184 #endif
185 #if BYTE_ORDER >= 0 /* big-endian */
186 {
187 /*
188 * On big-endian machines, we must arrange the bytes in the
189 * right order.
190 */
191 const md5_byte_t *xp = data;
192 int i;
193
194 # if BYTE_ORDER == 0
195 X = xbuf; /* (dynamic only) */
196 # else
197 # define xbuf X /* (static only) */
198 # endif
199 for (i = 0; i < 16; ++i, xp += 4)
200 xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
201 }
202 #endif
203 }
204
205 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
206
207 /* Round 1. */
208 /* Let [abcd k s i] denote the operation
209 a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
210 #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
211 #define SET(a, b, c, d, k, s, Ti)\
212 t = a + F(b,c,d) + X[k] + Ti;\
213 a = ROTATE_LEFT(t, s) + b
214 /* Do the following 16 operations. */
215 SET(a, b, c, d, 0, 7, T1);
216 SET(d, a, b, c, 1, 12, T2);
217 SET(c, d, a, b, 2, 17, T3);
218 SET(b, c, d, a, 3, 22, T4);
219 SET(a, b, c, d, 4, 7, T5);
220 SET(d, a, b, c, 5, 12, T6);
221 SET(c, d, a, b, 6, 17, T7);
222 SET(b, c, d, a, 7, 22, T8);
223 SET(a, b, c, d, 8, 7, T9);
224 SET(d, a, b, c, 9, 12, T10);
225 SET(c, d, a, b, 10, 17, T11);
226 SET(b, c, d, a, 11, 22, T12);
227 SET(a, b, c, d, 12, 7, T13);
228 SET(d, a, b, c, 13, 12, T14);
229 SET(c, d, a, b, 14, 17, T15);
230 SET(b, c, d, a, 15, 22, T16);
231 #undef SET
232
233 /* Round 2. */
234 /* Let [abcd k s i] denote the operation
235 a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
236 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
237 #define SET(a, b, c, d, k, s, Ti)\
238 t = a + G(b,c,d) + X[k] + Ti;\
239 a = ROTATE_LEFT(t, s) + b
240 /* Do the following 16 operations. */
241 SET(a, b, c, d, 1, 5, T17);
242 SET(d, a, b, c, 6, 9, T18);
243 SET(c, d, a, b, 11, 14, T19);
244 SET(b, c, d, a, 0, 20, T20);
245 SET(a, b, c, d, 5, 5, T21);
246 SET(d, a, b, c, 10, 9, T22);
247 SET(c, d, a, b, 15, 14, T23);
248 SET(b, c, d, a, 4, 20, T24);
249 SET(a, b, c, d, 9, 5, T25);
250 SET(d, a, b, c, 14, 9, T26);
251 SET(c, d, a, b, 3, 14, T27);
252 SET(b, c, d, a, 8, 20, T28);
253 SET(a, b, c, d, 13, 5, T29);
254 SET(d, a, b, c, 2, 9, T30);
255 SET(c, d, a, b, 7, 14, T31);
256 SET(b, c, d, a, 12, 20, T32);
257 #undef SET
258
259 /* Round 3. */
260 /* Let [abcd k s t] denote the operation
261 a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
262 #define H(x, y, z) ((x) ^ (y) ^ (z))
263 #define SET(a, b, c, d, k, s, Ti)\
264 t = a + H(b,c,d) + X[k] + Ti;\
265 a = ROTATE_LEFT(t, s) + b
266 /* Do the following 16 operations. */
267 SET(a, b, c, d, 5, 4, T33);
268 SET(d, a, b, c, 8, 11, T34);
269 SET(c, d, a, b, 11, 16, T35);
270 SET(b, c, d, a, 14, 23, T36);
271 SET(a, b, c, d, 1, 4, T37);
272 SET(d, a, b, c, 4, 11, T38);
273 SET(c, d, a, b, 7, 16, T39);
274 SET(b, c, d, a, 10, 23, T40);
275 SET(a, b, c, d, 13, 4, T41);
276 SET(d, a, b, c, 0, 11, T42);
277 SET(c, d, a, b, 3, 16, T43);
278 SET(b, c, d, a, 6, 23, T44);
279 SET(a, b, c, d, 9, 4, T45);
280 SET(d, a, b, c, 12, 11, T46);
281 SET(c, d, a, b, 15, 16, T47);
282 SET(b, c, d, a, 2, 23, T48);
283 #undef SET
284
285 /* Round 4. */
286 /* Let [abcd k s t] denote the operation
287 a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
288 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
289 #define SET(a, b, c, d, k, s, Ti)\
290 t = a + I(b,c,d) + X[k] + Ti;\
291 a = ROTATE_LEFT(t, s) + b
292 /* Do the following 16 operations. */
293 SET(a, b, c, d, 0, 6, T49);
294 SET(d, a, b, c, 7, 10, T50);
295 SET(c, d, a, b, 14, 15, T51);
296 SET(b, c, d, a, 5, 21, T52);
297 SET(a, b, c, d, 12, 6, T53);
298 SET(d, a, b, c, 3, 10, T54);
299 SET(c, d, a, b, 10, 15, T55);
300 SET(b, c, d, a, 1, 21, T56);
301 SET(a, b, c, d, 8, 6, T57);
302 SET(d, a, b, c, 15, 10, T58);
303 SET(c, d, a, b, 6, 15, T59);
304 SET(b, c, d, a, 13, 21, T60);
305 SET(a, b, c, d, 4, 6, T61);
306 SET(d, a, b, c, 11, 10, T62);
307 SET(c, d, a, b, 2, 15, T63);
308 SET(b, c, d, a, 9, 21, T64);
309 #undef SET
310
311 /* Then perform the following additions. (That is increment each
312 of the four registers by the value it had before this block
313 was started.) */
314 pms->abcd[0] += a;
315 pms->abcd[1] += b;
316 pms->abcd[2] += c;
317 pms->abcd[3] += d;
318 }
319
320 void
321 md5_init(md5_state_t *pms)
322 {
323 pms->count[0] = pms->count[1] = 0;
324 pms->abcd[0] = 0x67452301;
325 pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
326 pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
327 pms->abcd[3] = 0x10325476;
328 }
329
330 void
331 md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
332 {
333 const md5_byte_t *p = data;
334 int left = nbytes;
335 int offset = (pms->count[0] >> 3) & 63;
336 md5_word_t nbits = (md5_word_t)(nbytes << 3);
337
338 if (nbytes <= 0)
339 return;
340
341 /* Update the message length. */
342 pms->count[1] += nbytes >> 29;
343 pms->count[0] += nbits;
344 if (pms->count[0] < nbits)
345 pms->count[1]++;
346
347 /* Process an initial partial block. */
348 if (offset) {
349 int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
350
351 memcpy(pms->buf + offset, p, copy);
352 if (offset + copy < 64)
353 return;
354 p += copy;
355 left -= copy;
356 md5_process(pms, pms->buf);
357 }
358
359 /* Process full blocks. */
360 for (; left >= 64; p += 64, left -= 64)
361 md5_process(pms, p);
362
363 /* Process a final partial block. */
364 if (left)
365 memcpy(pms->buf, p, left);
366 }
367
368 void
369 md5_finish(md5_state_t *pms, md5_byte_t digest[16])
370 {
371 static const md5_byte_t pad[64] = {
372 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
373 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
374 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
375 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
376 };
377 md5_byte_t data[8];
378 int i;
379
380 /* Save the length before padding. */
381 for (i = 0; i < 8; ++i)
382 data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
383 /* Pad to 56 bytes mod 64. */
384 md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
385 /* Append the length. */
386 md5_append(pms, data, 8);
387 for (i = 0; i < 16; ++i)
388 digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
389 }
0 /*
1 * md5.h was taken from "RFC1321-based (RSA-free) MD5 library" by L. Peter
2 * Deutsch at http://sourceforge.net/projects/libmd5-rfc/ in October 2011.
3 *
4 * The code was not modified when integrated into the Dillo project, but you
5 * should check the source repository to be sure that there have not been
6 * modifications since this notice.
7 */
8
9 /*
10 Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
11
12 This software is provided 'as-is', without any express or implied
13 warranty. In no event will the authors be held liable for any damages
14 arising from the use of this software.
15
16 Permission is granted to anyone to use this software for any purpose,
17 including commercial applications, and to alter it and redistribute it
18 freely, subject to the following restrictions:
19
20 1. The origin of this software must not be misrepresented; you must not
21 claim that you wrote the original software. If you use this software
22 in a product, an acknowledgment in the product documentation would be
23 appreciated but is not required.
24 2. Altered source versions must be plainly marked as such, and must not be
25 misrepresented as being the original software.
26 3. This notice may not be removed or altered from any source distribution.
27
28 L. Peter Deutsch
29 ghost@aladdin.com
30
31 */
32 /* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
33 /*
34 Independent implementation of MD5 (RFC 1321).
35
36 This code implements the MD5 Algorithm defined in RFC 1321, whose
37 text is available at
38 http://www.ietf.org/rfc/rfc1321.txt
39 The code is derived from the text of the RFC, including the test suite
40 (section A.5) but excluding the rest of Appendix A. It does not include
41 any code or documentation that is identified in the RFC as being
42 copyrighted.
43
44 The original and principal author of md5.h is L. Peter Deutsch
45 <ghost@aladdin.com>. Other authors are noted in the change history
46 that follows (in reverse chronological order):
47
48 2002-04-13 lpd Removed support for non-ANSI compilers; removed
49 references to Ghostscript; clarified derivation from RFC 1321;
50 now handles byte order either statically or dynamically.
51 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
52 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
53 added conditionalization for C++ compilation from Martin
54 Purschke <purschke@bnl.gov>.
55 1999-05-03 lpd Original version.
56 */
57
58 #ifndef md5_INCLUDED
59 # define md5_INCLUDED
60
61 /*
62 * This package supports both compile-time and run-time determination of CPU
63 * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
64 * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
65 * defined as non-zero, the code will be compiled to run only on big-endian
66 * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
67 * run on either big- or little-endian CPUs, but will run slightly less
68 * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
69 */
70
71 typedef unsigned char md5_byte_t; /* 8-bit byte */
72 typedef unsigned int md5_word_t; /* 32-bit word */
73
74 /* Define the state of the MD5 Algorithm. */
75 typedef struct md5_state_s {
76 md5_word_t count[2]; /* message length in bits, lsw first */
77 md5_word_t abcd[4]; /* digest buffer */
78 md5_byte_t buf[64]; /* accumulate block */
79 } md5_state_t;
80
81 #ifdef __cplusplus
82 extern "C"
83 {
84 #endif
85
86 /* Initialize the algorithm. */
87 void md5_init(md5_state_t *pms);
88
89 /* Append a string to the message. */
90 void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
91
92 /* Finish the message and return the digest. */
93 void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
94
95 #ifdef __cplusplus
96 } /* end extern "C" */
97 #endif
98
99 #endif /* md5_INCLUDED */
206206
207207 static void Menu_stylesheet_cb(Fl_Widget*, void *vUrl)
208208 {
209 int mb = Fl::event_button();
209210 const DilloUrl *url = (const DilloUrl *) vUrl;
210 a_UIcmd_open_url(popup_bw, url);
211
212 if (mb == 1) {
213 a_UIcmd_open_url(popup_bw, url);
214 } else if (mb == 2) {
215 if (prefs.middle_click_opens_new_tab) {
216 int focus = prefs.focus_new_tab ? 1 : 0;
217 if (Fl::event_state(FL_SHIFT)) focus = !focus;
218 a_UIcmd_open_url_nt(popup_bw, url, focus);
219 } else {
220 a_UIcmd_open_url_nw(popup_bw, url);
221 }
222 }
211223 }
212224
213225 /*
314326
315327 has_bugs == TRUE ? pm[1].activate() : pm[1].deactivate();
316328
317 if (strncmp(URL_STR(url), "dpi:/vsource/", 13) == 0)
329 if (dStrAsciiCasecmp(URL_SCHEME(url), "dpi") == 0 &&
330 strncmp(URL_PATH(url), "/vsource/", 9) == 0)
318331 pm[0].deactivate();
319332 else
320333 pm[0].activate();
140140
141141 /* HTML try */
142142 for (i = 0; i < Size && dIsspace(p[i]); ++i);
143 if ((Size - i >= 5 && !dStrncasecmp(p+i, "<html", 5)) ||
144 (Size - i >= 5 && !dStrncasecmp(p+i, "<head", 5)) ||
145 (Size - i >= 6 && !dStrncasecmp(p+i, "<title", 6)) ||
146 (Size - i >= 14 && !dStrncasecmp(p+i, "<!doctype html", 14)) ||
143 if ((Size - i >= 5 && !dStrnAsciiCasecmp(p+i, "<html", 5)) ||
144 (Size - i >= 5 && !dStrnAsciiCasecmp(p+i, "<head", 5)) ||
145 (Size - i >= 6 && !dStrnAsciiCasecmp(p+i, "<title", 6)) ||
146 (Size - i >= 14 && !dStrnAsciiCasecmp(p+i, "<!doctype html", 14)) ||
147147 /* this line is workaround for FTP through the Squid proxy */
148 (Size - i >= 17 && !dStrncasecmp(p+i, "<!-- HTML listing", 17))) {
148 (Size - i >= 17 && !dStrnAsciiCasecmp(p+i, "<!-- HTML listing", 17))) {
149149
150150 Type = DT_TEXT_HTML;
151151 st = 0;
152152 /* Images */
153 } else if (Size >= 4 && !dStrncasecmp(p, "GIF8", 4)) {
153 } else if (Size >= 4 && !strncmp(p, "GIF8", 4)) {
154154 Type = DT_IMAGE_GIF;
155155 st = 0;
156 } else if (Size >= 4 && !dStrncasecmp(p, "\x89PNG", 4)) {
156 } else if (Size >= 4 && !strncmp(p, "\x89PNG", 4)) {
157157 Type = DT_IMAGE_PNG;
158158 st = 0;
159 } else if (Size >= 2 && !dStrncasecmp(p, "\xff\xd8", 2)) {
159 } else if (Size >= 2 && !strncmp(p, "\xff\xd8", 2)) {
160160 /* JPEG has the first 2 bytes set to 0xffd8 in BigEndian - looking
161161 * at the character representation should be machine independent. */
162162 Type = DT_IMAGE_JPG;
220220 if (!(str = type))
221221 return;
222222
223 for (s = str; *s && !iscntrl((uchar_t)*s) && !strchr(tspecials_space, *s);
224 s++) ;
223 for (s = str; *s && isascii((uchar_t)*s) && !iscntrl((uchar_t)*s) &&
224 !strchr(tspecials_space, *s); s++) ;
225225 if (major)
226226 *major = dStrndup(str, s - str);
227227
228228 if (*s == '/') {
229 for (str = ++s;
230 *s && !iscntrl((uchar_t)*s) && !strchr(tspecials_space, *s); s++) ;
229 for (str = ++s; *s && isascii((uchar_t)*s) && !iscntrl((uchar_t)*s) &&
230 !strchr(tspecials_space, *s); s++) ;
231231 if (minor)
232232 *minor = dStrndup(str, s - str);
233233 }
234234 if (charset && *s &&
235 (dStrncasecmp(type, "text/", 5) == 0 ||
236 dStrncasecmp(type, "application/xhtml+xml", 21) == 0)) {
235 (dStrnAsciiCasecmp(type, "text/", 5) == 0 ||
236 dStrnAsciiCasecmp(type, "application/xhtml+xml", 21) == 0)) {
237237 /* "charset" parameter defined for text media type in RFC 2046,
238238 * application/xhtml+xml in RFC 3236.
239239 *
245245 const char terminators[] = " ;\t";
246246 const char key[] = "charset";
247247
248 if ((s = dStristr(str, key)) &&
248 if ((s = dStriAsciiStr(str, key)) &&
249249 (s == str || strchr(terminators, s[-1]))) {
250250 s += sizeof(key) - 1;
251251 for ( ; *s == ' ' || *s == '\t'; ++s);
282282 a_Misc_parse_content_type(ct1, &major1, &minor1, &charset1);
283283 a_Misc_parse_content_type(ct2, &major2, &minor2, &charset2);
284284
285 if (major1 && major2 && !dStrcasecmp(major1, major2) &&
286 minor1 && minor2 && !dStrcasecmp(minor1, minor2) &&
285 if (major1 && major2 && !dStrAsciiCasecmp(major1, major2) &&
286 minor1 && minor2 && !dStrAsciiCasecmp(minor1, minor2) &&
287287 ((!charset1 && !charset2) ||
288 (charset1 && charset2 && !dStrcasecmp(charset1, charset2)) ||
289 (!charset1 && charset2 && !dStrcasecmp(charset2, "UTF-8")) ||
290 (charset1 && !charset2 && !dStrcasecmp(charset1, "UTF-8")))) {
288 (charset1 && charset2 && !dStrAsciiCasecmp(charset1, charset2)) ||
289 (!charset1 && charset2 && !dStrAsciiCasecmp(charset2, "UTF-8")) ||
290 (charset1 && !charset2 && !dStrAsciiCasecmp(charset1, "UTF-8")))) {
291291 ret = 0;
292292 } else {
293293 ret = 1;
327327 return 0; /* there's no mismatch without server type */
328328
329329 for (i = 1; MimeTypes[i].str; ++i)
330 if (dStrncasecmp(EntryType, MimeTypes[i].str, MimeTypes[i].len) == 0)
330 if (dStrnAsciiCasecmp(EntryType, MimeTypes[i].str, MimeTypes[i].len) ==0)
331331 break;
332332
333333 if (!MimeTypes[i].str) {
334334 /* type not found, no mismatch */
335335 st = 0;
336 } else if (dStrncasecmp(EntryType, "image/", 6) == 0 &&
337 !dStrncasecmp(DetectedType,MimeTypes[i].str,MimeTypes[i].len)){
336 } else if (dStrnAsciiCasecmp(EntryType, "image/", 6) == 0 &&
337 !dStrnAsciiCasecmp(DetectedType, MimeTypes[i].str,
338 MimeTypes[i].len)){
338339 /* An image, and there's an exact match */
339340 st = 0;
340 } else if (dStrncasecmp(EntryType, "text/", 5) ||
341 dStrncasecmp(DetectedType, "application/", 12)) {
341 } else if (dStrnAsciiCasecmp(EntryType, "text/", 5) ||
342 dStrnAsciiCasecmp(DetectedType, "application/", 12)) {
342343 /* Not an application sent as text */
343344 st = 0;
344 } else if (dStrncasecmp(EntryType, "application/xhtml+xml", 21) &&
345 dStrncasecmp(DetectedType, "text/html", 9)) {
345 } else if (dStrnAsciiCasecmp(EntryType, "application/xhtml+xml", 21) &&
346 dStrnAsciiCasecmp(DetectedType, "text/html", 9)) {
346347 /* XML version of HTML */
347348 st = 0;
348349 }
480480 a_Nav_cancel_expect(bw);
481481 if (a_Nav_stack_size(bw)) {
482482 h_url = a_History_get_url(NAV_TOP_UIDX(bw));
483 if (strncmp(URL_STR(h_url), "dpi:/vsource/", 13) == 0) {
484 /* disable reload for view source dpi */
485 confirmed = 0;
483 if (dStrAsciiCasecmp(URL_SCHEME(h_url), "dpi") == 0 &&
484 strncmp(URL_PATH(h_url), "/vsource/", 9) == 0) {
485 /* allow reload for view source dpi */
486 confirmed = 1;
486487 } else if (URL_FLAGS(h_url) & URL_Post) {
487488 /* Attempt to repost data, let's confirm... */
488489 choice = a_Dialog_choice5("Repost form data?",
126126
127127 switch (node->type) {
128128 case PREFS_BOOL:
129 *(bool_t *)node->pref = (!dStrcasecmp(value, "yes") ||
130 !dStrcasecmp(value, "true"));
129 *(bool_t *)node->pref = (!dStrAsciiCasecmp(value, "yes") ||
130 !dStrAsciiCasecmp(value, "true"));
131131 break;
132132 case PREFS_COLOR:
133133 *(int32_t *)node->pref = a_Color_parse(value, *(int32_t*)node->pref,&st);
166166 &prefs.width, &prefs.height);
167167 break;
168168 case PREFS_FILTER:
169 if (!dStrcasecmp(value, "same_domain"))
169 if (!dStrAsciiCasecmp(value, "same_domain"))
170170 prefs.filter_auto_requests = PREFS_FILTER_SAME_DOMAIN;
171171 else {
172 if (dStrcasecmp(value, "allow_all"))
172 if (dStrAsciiCasecmp(value, "allow_all"))
173173 MSG_WARN("prefs: unrecognized value for filter_auto_requests\n");
174174 prefs.filter_auto_requests = PREFS_FILTER_ALLOW_ALL;
175175 }
176176 break;
177177 case PREFS_PANEL_SIZE:
178 if (!dStrcasecmp(value, "tiny"))
178 if (!dStrAsciiCasecmp(value, "tiny"))
179179 prefs.panel_size = P_tiny;
180 else if (!dStrcasecmp(value, "small"))
180 else if (!dStrAsciiCasecmp(value, "small"))
181181 prefs.panel_size = P_small;
182182 else /* default to "medium" */
183183 prefs.panel_size = P_medium;
302302 *c = '\0';
303303 dStrstrip(p->value.strVal);
304304
305 if (strcmp (p->value.strVal, "serif") == 0)
305 if (dStrAsciiCasecmp (p->value.strVal, "serif") == 0)
306306 fontName = prefs.font_serif;
307 else if (strcmp (p->value.strVal, "sans-serif") == 0)
307 else if (dStrAsciiCasecmp (p->value.strVal, "sans-serif") == 0)
308308 fontName = prefs.font_sans_serif;
309 else if (strcmp (p->value.strVal, "cursive") == 0)
309 else if (dStrAsciiCasecmp (p->value.strVal, "cursive") == 0)
310310 fontName = prefs.font_cursive;
311 else if (strcmp (p->value.strVal, "fantasy") == 0)
311 else if (dStrAsciiCasecmp (p->value.strVal, "fantasy") == 0)
312312 fontName = prefs.font_fantasy;
313 else if (strcmp (p->value.strVal, "monospace") == 0)
313 else if (dStrAsciiCasecmp (p->value.strVal, "monospace") == 0)
314314 fontName = prefs.font_monospace;
315315 else if (Font::exists(layout, p->value.strVal))
316316 fontName = p->value.strVal;
330330 if (p->type == CSS_TYPE_ENUM) {
331331 switch (p->value.intVal) {
332332 case CSS_FONT_SIZE_XX_SMALL:
333 fontAttrs.size = roundInt(11.0 * prefs.font_factor);
333 fontAttrs.size = roundInt(8.1 * prefs.font_factor);
334334 break;
335335 case CSS_FONT_SIZE_X_SMALL:
336 fontAttrs.size = roundInt(12.0 * prefs.font_factor);
336 fontAttrs.size = roundInt(9.7 * prefs.font_factor);
337337 break;
338338 case CSS_FONT_SIZE_SMALL:
339 fontAttrs.size = roundInt(13.0 * prefs.font_factor);
339 fontAttrs.size = roundInt(11.7 * prefs.font_factor);
340340 break;
341341 case CSS_FONT_SIZE_MEDIUM:
342342 fontAttrs.size = roundInt(14.0 * prefs.font_factor);
343343 break;
344344 case CSS_FONT_SIZE_LARGE:
345 fontAttrs.size = roundInt(16.8 * prefs.font_factor);
345346 break;
346347 case CSS_FONT_SIZE_X_LARGE:
347 fontAttrs.size = roundInt(16.0 * prefs.font_factor);
348 fontAttrs.size = roundInt(20.2 * prefs.font_factor);
348349 break;
349350 case CSS_FONT_SIZE_XX_LARGE:
350 fontAttrs.size = roundInt(17.0 * prefs.font_factor);
351 fontAttrs.size = roundInt(24.2 * prefs.font_factor);
351352 break;
352353 case CSS_FONT_SIZE_SMALLER:
353 fontAttrs.size -= roundInt(1.0 * prefs.font_factor);
354 fontAttrs.size = roundInt(fontAttrs.size * 0.83 *
355 prefs.font_factor);
354356 break;
355357 case CSS_FONT_SIZE_LARGER:
356 fontAttrs.size += roundInt(1.0 * prefs.font_factor);
358 fontAttrs.size = roundInt(fontAttrs.size * 1.2 *
359 prefs.font_factor);
357360 break;
358361 default:
359362 assert(false); // invalid font-size enum
560563 break;
561564 case CSS_PROPERTY_TEXT_INDENT:
562565 computeLength (&attrs->textIndent, p->value.intVal, attrs->font);
566 break;
567 case CSS_PROPERTY_TEXT_TRANSFORM:
568 attrs->textTransform = (TextTransform) p->value.intVal;
563569 break;
564570 case CSS_PROPERTY_VERTICAL_ALIGN:
565571 attrs->valign = (VAlignType) p->value.intVal;
8080 a_Html_parse_length (html, attrbuf));
8181
8282 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "align"))) {
83 if (dStrcasecmp (attrbuf, "left") == 0)
83 if (dStrAsciiCasecmp (attrbuf, "left") == 0)
8484 html->styleEngine->setNonCssHint (CSS_PROPERTY_TEXT_ALIGN,
8585 CSS_TYPE_ENUM, TEXT_ALIGN_LEFT);
86 else if (dStrcasecmp (attrbuf, "right") == 0)
86 else if (dStrAsciiCasecmp (attrbuf, "right") == 0)
8787 html->styleEngine->setNonCssHint (CSS_PROPERTY_TEXT_ALIGN,
8888 CSS_TYPE_ENUM, TEXT_ALIGN_RIGHT);
89 else if (dStrcasecmp (attrbuf, "center") == 0)
89 else if (dStrAsciiCasecmp (attrbuf, "center") == 0)
9090 html->styleEngine->setNonCssHint (CSS_PROPERTY_TEXT_ALIGN,
9191 CSS_TYPE_ENUM, TEXT_ALIGN_CENTER);
9292 }
346346 if (a_Html_get_attr(html, tag, tagsize, "nowrap"))
347347 html->styleEngine->setNonCssHint(CSS_PROPERTY_WHITE_SPACE,
348348 CSS_TYPE_ENUM, WHITE_SPACE_NOWRAP);
349 else
350 html->styleEngine->setNonCssHint(CSS_PROPERTY_WHITE_SPACE,
351 CSS_TYPE_ENUM, WHITE_SPACE_NORMAL);
352349
353350 a_Html_tag_set_align_attr (html, tag, tagsize);
354351
596596 /* Filter URL string */
597597 new_urlstr = a_Url_string_strip_delimiters(urlstr);
598598
599 if (!dStrncasecmp(new_urlstr, "file:", 5)) {
599 if (!dStrnAsciiCasecmp(new_urlstr, "file:", 5)) {
600600 /* file URI */
601601 ch = new_urlstr[5];
602602 if (!ch || ch == '.') {
5353 #define URL_STR_FIELD_CMP(s1,s2) \
5454 (s1) && (s2) ? strcmp(s1,s2) : !(s1) && !(s2) ? 0 : (s1) ? 1 : -1
5555 #define URL_STR_FIELD_I_CMP(s1,s2) \
56 (s1) && (s2) ? dStrcasecmp(s1,s2) : !(s1) && !(s2) ? 0 : (s1) ? 1 : -1
56 (s1) && (s2) ? dStrAsciiCasecmp(s1,s2) : !(s1) && !(s2) ? 0 : (s1) ? 1 : -1
5757
5858 /*
5959 * Return the url as a string.
585585 newstr = dNew(char, 6*strlen(str)+1);
586586
587587 for (c = newstr; *str; str++)
588 if ((dIsalnum(*str) && !(*str & 0x80)) || strchr(verbatim, *str))
589 /* we really need isalnum for the "C" locale */
588 if ((dIsalnum(*str) && isascii(*str)) || strchr(verbatim, *str))
590589 *c++ = *str;
591590 else if (*str == ' ')
592591 *c++ = '+';
651650 _MSG("an IPv4 address\n");
652651 return TRUE;
653652 }
654 if (*host == '[' &&
655 (len == strspn(host, "0123456789abcdefABCDEF:.[]"))) {
653 if (strchr(host, ':') &&
654 (len == strspn(host, "0123456789abcdefABCDEF:."))) {
656655 /* The precise format is shown in section 3.2.2 of rfc 3986 */
657 _MSG("an IPv6 address\n");
656 MSG("an IPv6 address\n");
658657 return TRUE;
659658 }
660659 return FALSE;
701700
702701 for (i = 0; i < tld_num; i++) {
703702 if (strlen(tlds[i]) == (uint_t) tld_len &&
704 !dStrncasecmp(tlds[i], host + start, tld_len)) {
703 !dStrnAsciiCasecmp(tlds[i], host + start, tld_len)) {
705704 _MSG("TLD code matched %s\n", tlds[i]);
706705 ret++;
707706 break;
758757 if (!u1 || !u2)
759758 return FALSE;
760759
761 return dStrcasecmp(Url_host_find_public_suffix(URL_HOST(u1)),
762 Url_host_find_public_suffix(URL_HOST(u2))) ? FALSE :TRUE;
763 }
760 return dStrAsciiCasecmp(Url_host_find_public_suffix(URL_HOST(u1)),
761 Url_host_find_public_suffix(URL_HOST(u2)))
762 ? FALSE : TRUE;
763 }
9494
9595 } else {
9696 /* A non-RootUrl. At this moment we only handle image-children */
97 if (!dStrncasecmp(Type, "image/", 6)) {
97 if (!dStrnAsciiCasecmp(Type, "image/", 6)) {
9898 dw = (Widget*) a_Mime_set_viewer(Type, Web, Call, Data);
9999 } else {
100100 MSG_HTTP("'%s' cannot be displayed as image; has media type '%s'\n",
917917
918918 /* SOME IP ADDRS */
919919
920 a_Cookies_set("name=val", "[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]",
920 a_Cookies_set("name=val", "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210",
921921 "/", NULL);
922922 expect(__LINE__, "Cookie: name=val\r\n", "http",
923 "[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", "/");
924
925 a_Cookies_set("name=val", "[::FFFF:129.144.52.38]", "/", NULL);
926 expect(__LINE__, "Cookie: name=val\r\n", "http", "[::FFFF:129.144.52.38]",
923 "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", "/");
924
925 a_Cookies_set("name=val", "::FFFF:129.144.52.38", "/", NULL);
926 expect(__LINE__, "Cookie: name=val\r\n", "http", "::FFFF:129.144.52.38",
927927 "/");
928928
929929 a_Cookies_set("name=val", "127.0.0.1", "/", NULL);
6868
6969 char buf[16];
7070 strcpy (buf, numbers[textblockNo]);
71 buf[0] = toupper (buf[0]);
71 buf[0] = lout::misc::AsciiToupper (buf[0]);
7272 topTextblock->addText (buf, headingStyle);
7373 topTextblock->addParbreak (5, headingStyle);
7474
7575 for (int i = 0; i < 30; i++) {
7676 strcpy (buf, numbers[textblockNo]);
7777 if (i == 0)
78 buf[0] = toupper (buf[0]);
78 buf[0] = lout::misc::AsciiToupper (buf[0]);
7979 strcat (buf, i == 29 ? "." : ",");
8080
8181 topTextblock->addText (buf, wordStyle);
108108 for (int i = 0; i < 10; i++) {
109109 char buf[16];
110110 strcpy (buf, numbers[i]);
111 buf[0] = toupper (buf[0]);
111 buf[0] = lout::misc::AsciiToupper (buf[0]);
112112 buttonLabel[i] = strdup(buf);
113113 Fl_Button *button = new Fl_Button(0, 20 * i, 50, 20, buttonLabel[i]);
114114 button->callback (anchorCallback, (void*)(long)i);