diff --git a/qse/include/qse/cmn/Makefile.am b/qse/include/qse/cmn/Makefile.am index 1d45c208..62a72011 100644 --- a/qse/include/qse/cmn/Makefile.am +++ b/qse/include/qse/cmn/Makefile.am @@ -39,6 +39,7 @@ pkginclude_HEADERS = \ time.h \ tio.h \ tre.h \ + uri.h \ utf8.h \ xma.h diff --git a/qse/include/qse/cmn/Makefile.in b/qse/include/qse/cmn/Makefile.in index 68fb1134..62b8690a 100644 --- a/qse/include/qse/cmn/Makefile.in +++ b/qse/include/qse/cmn/Makefile.in @@ -55,8 +55,8 @@ am__pkginclude_HEADERS_DIST = alg.h chr.h cp949.h cp950.h dll.h env.h \ fio.h fma.h fmt.h fs.h gdl.h glob.h htb.h hton.h ipad.h lda.h \ main.h map.h mbwc.h mem.h nwad.h nwif.h nwio.h oht.h opt.h \ path.h pio.h pma.h rbt.h rex.h sio.h sll.h slmb.h stdio.h \ - str.h time.h tio.h tre.h utf8.h xma.h Mmgr.hpp StdMmgr.hpp \ - Mmged.hpp + str.h time.h tio.h tre.h uri.h utf8.h xma.h Mmgr.hpp \ + StdMmgr.hpp Mmged.hpp am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -247,7 +247,7 @@ pkginclude_HEADERS = alg.h chr.h cp949.h cp950.h dll.h env.h fio.h \ fma.h fmt.h fs.h gdl.h glob.h htb.h hton.h ipad.h lda.h main.h \ map.h mbwc.h mem.h nwad.h nwif.h nwio.h oht.h opt.h path.h \ pio.h pma.h rbt.h rex.h sio.h sll.h slmb.h stdio.h str.h \ - time.h tio.h tre.h utf8.h xma.h $(am__append_1) + time.h tio.h tre.h uri.h utf8.h xma.h $(am__append_1) all: all-am .SUFFIXES: diff --git a/qse/include/qse/cmn/alg.h b/qse/include/qse/cmn/alg.h index f433dcc3..7eee8f96 100644 --- a/qse/include/qse/cmn/alg.h +++ b/qse/include/qse/cmn/alg.h @@ -170,6 +170,23 @@ qse_uint64_t qse_randxs64 ( #endif + +qse_size_t qse_enbase64 ( + const qse_uint8_t* in, + qse_size_t isz, + qse_mchar_t* out, + qse_size_t osz, + qse_size_t* xsz +); + +qse_size_t qse_debase64 ( + const qse_mchar_t* in, + qse_size_t isz, + qse_uint8_t* out, + qse_size_t osz, + qse_size_t* xsz +); + #ifdef __cplusplus } #endif diff --git a/qse/include/qse/cmn/mbwc.h b/qse/include/qse/cmn/mbwc.h index 874b0f5b..1bdc44b2 100644 --- a/qse/include/qse/cmn/mbwc.h +++ b/qse/include/qse/cmn/mbwc.h @@ -187,6 +187,13 @@ qse_mchar_t* qse_wcstombsdupwithcmgr ( qse_cmgr_t* cmgr ); +qse_mchar_t* qse_wcntombsdupwithcmgr ( + const qse_wchar_t* wcs, + qse_size_t len, + qse_mmgr_t* mmgr, + qse_cmgr_t* cmgr +); + qse_mchar_t* qse_wcsatombsdupwithcmgr ( const qse_wchar_t* wcs[], qse_mmgr_t* mmgr, @@ -369,6 +376,12 @@ qse_mchar_t* qse_wcstombsdup ( qse_mmgr_t* mmgr ); +qse_mchar_t* qse_wcsntombsdup ( + const qse_wchar_t* wcs, + qse_size_t len, + qse_mmgr_t* mmgr +); + qse_mchar_t* qse_wcsatombsdup ( const qse_wchar_t* wcs[], qse_mmgr_t* mmgr diff --git a/qse/include/qse/cmn/str.h b/qse/include/qse/cmn/str.h index f300efe4..dded784b 100644 --- a/qse/include/qse/cmn/str.h +++ b/qse/include/qse/cmn/str.h @@ -929,12 +929,23 @@ int qse_mbszcmp ( qse_size_t n ); +int qse_mbszcasecmp ( + const qse_mchar_t* s1, + const qse_mchar_t* s2, + qse_size_t n +); + int qse_wcszcmp ( const qse_wchar_t* s1, const qse_wchar_t* s2, qse_size_t n ); +int qse_wcszcasecmp ( + const qse_wchar_t* s1, + const qse_wchar_t* s2, + qse_size_t n +); #ifdef QSE_CHAR_IS_MCHAR # define qse_strcmp(s1,s2) qse_mbscmp(s1,s2) @@ -944,6 +955,7 @@ int qse_wcszcmp ( # define qse_strxcasecmp(s1,ln1,s2) qse_mbsxcasecmp(s1,ln1,s2) # define qse_strxncasecmp(s1,ln1,s2,ln2) qse_mbsxncasecmp(s1,ln1,s2,ln2) # define qse_strzcmp(s1,s2,n) qse_mbszcmp(s1,s2,n) +# define qse_strzcasecmp(s1,s2,n) qse_mbszcasecmp(s1,s2,n) #else # define qse_strcmp(s1,s2) qse_wcscmp(s1,s2) # define qse_strxcmp(s1,ln1,s2) qse_wcsxcmp(s1,ln1,s2) @@ -952,6 +964,7 @@ int qse_wcszcmp ( # define qse_strxcasecmp(s1,ln1,s2) qse_wcsxcasecmp(s1,ln1,s2) # define qse_strxncasecmp(s1,ln1,s2,ln2) qse_wcsxncasecmp(s1,ln1,s2,ln2) # define qse_strzcmp(s1,s2,n) qse_wcszcmp(s1,s2,n) +# define qse_strzcasecmp(s1,s2,n) qse_wcszcasecmp(s1,s2,n) #endif qse_mchar_t* qse_mbsdup ( @@ -984,6 +997,11 @@ qse_mchar_t* qse_mbsadup ( qse_mmgr_t* mmgr ); +qse_mchar_t* qse_mbsxadup ( + const qse_mcstr_t str[], + qse_mmgr_t* mmgr +); + qse_wchar_t* qse_wcsdup ( const qse_wchar_t* str, qse_mmgr_t* mmgr @@ -1014,18 +1032,25 @@ qse_wchar_t* qse_wcsadup ( qse_mmgr_t* mmgr ); +qse_wchar_t* qse_wcsxadup ( + const qse_wcstr_t str[], + qse_mmgr_t* mmgr +); + #ifdef QSE_CHAR_IS_MCHAR # define qse_strdup(s,mmgr) qse_mbsdup(s,mmgr) # define qse_strdup2(s1,s2,mmgr) qse_mbsdup2(s1,s2,mmgr) # define qse_strxdup(s,l,mmgr) qse_mbsxdup(s,l,mmgr) # define qse_strxdup2(s1,l1,s2,l2,mmgr) qse_mbsxdup(s1,l1,s2,l2,mmgr) # define qse_stradup(sa,mmgr) qse_mbsadup(sa,mmgr) +# define qse_strxadup(sa,mmgr) qse_mbsxadup(sa,mmgr) #else # define qse_strdup(s,mmgr) qse_wcsdup(s,mmgr) # define qse_strdup2(s1,s2,mmgr) qse_wcsdup2(s1,s2,mmgr) # define qse_strxdup(s,l,mmgr) qse_wcsxdup(s,l,mmgr) # define qse_strxdup2(s1,l1,s2,l2,mmgr) qse_wcsxdup(s1,l1,s2,l2,mmgr) # define qse_stradup(sa,mmgr) qse_wcsadup(sa,mmgr) +# define qse_strxadup(sa,mmgr) qse_wcsxadup(sa,mmgr) #endif /** diff --git a/qse/include/qse/net/httpd.h b/qse/include/qse/net/httpd.h index 9a2cdc84..c5fc5233 100644 --- a/qse/include/qse/net/httpd.h +++ b/qse/include/qse/net/httpd.h @@ -709,6 +709,12 @@ qse_httpd_server_t* qse_httpd_attachserverstd ( qse_size_t xtnsize ); +void* qse_httpd_getserverxtnstd ( + qse_httpd_t* httpd, + qse_httpd_server_t* server +); + + int qse_httpd_loopstd ( qse_httpd_t* httpd, qse_httpd_cbstd_t* cbstd, diff --git a/qse/lib/cmn/Makefile.am b/qse/lib/cmn/Makefile.am index 426e46ae..f9863ff1 100644 --- a/qse/lib/cmn/Makefile.am +++ b/qse/lib/cmn/Makefile.am @@ -22,6 +22,7 @@ noinst_HEADERS = \ tre-stack.h libqsecmn_la_SOURCES = \ + alg-base64.c \ alg-rand.c \ alg-search.c \ alg-sort.c \ @@ -100,6 +101,7 @@ libqsecmn_la_SOURCES = \ tre-match-parallel.c \ tre-parse.c \ tre-stack.c \ + uri.c \ utf8.c \ xma.c diff --git a/qse/lib/cmn/Makefile.in b/qse/lib/cmn/Makefile.in index 8dfda7bb..888cfda8 100644 --- a/qse/lib/cmn/Makefile.in +++ b/qse/lib/cmn/Makefile.in @@ -82,11 +82,11 @@ am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libqsecmn_la_DEPENDENCIES = $(am__DEPENDENCIES_1) -am_libqsecmn_la_OBJECTS = alg-rand.lo alg-search.lo alg-sort.lo \ - assert.lo chr.lo cp949.lo cp950.lo dll.lo env.lo gdl.lo htb.lo \ - fio.lo fma.lo fmt.lo fs.lo fs-err.lo fs-move.lo glob.lo \ - hton.lo ipad.lo lda.lo main.lo mbwc.lo mbwc-str.lo mem.lo \ - nwad.lo nwif.lo nwio.lo oht.lo opt.lo path-basename.lo \ +am_libqsecmn_la_OBJECTS = alg-base64.lo alg-rand.lo alg-search.lo \ + alg-sort.lo assert.lo chr.lo cp949.lo cp950.lo dll.lo env.lo \ + gdl.lo htb.lo fio.lo fma.lo fmt.lo fs.lo fs-err.lo fs-move.lo \ + glob.lo hton.lo ipad.lo lda.lo main.lo mbwc.lo mbwc-str.lo \ + mem.lo nwad.lo nwif.lo nwio.lo oht.lo opt.lo path-basename.lo \ path-canon.lo pio.lo pma.lo rbt.lo rex.lo sio.lo sll.lo \ slmb.lo stdio.lo str-beg.lo str-cat.lo str-chr.lo str-cnv.lo \ str-cmp.lo str-cpy.lo str-del.lo str-dup.lo str-dynm.lo \ @@ -96,7 +96,7 @@ am_libqsecmn_la_OBJECTS = alg-rand.lo alg-search.lo alg-sort.lo \ str-str.lo str-subst.lo str-tok.lo str-trm.lo str-word.lo \ time.lo tio.lo tre.lo tre-ast.lo tre-compile.lo \ tre-match-backtrack.lo tre-match-parallel.lo tre-parse.lo \ - tre-stack.lo utf8.lo xma.lo + tre-stack.lo uri.lo utf8.lo xma.lo libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS) libqsecmn_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ @@ -312,6 +312,7 @@ noinst_HEADERS = \ tre-stack.h libqsecmn_la_SOURCES = \ + alg-base64.c \ alg-rand.c \ alg-search.c \ alg-sort.c \ @@ -390,6 +391,7 @@ libqsecmn_la_SOURCES = \ tre-match-parallel.c \ tre-parse.c \ tre-stack.c \ + uri.c \ utf8.c \ xma.c @@ -478,6 +480,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Mmgr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StdMmgr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alg-base64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alg-rand.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alg-search.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alg-sort.Plo@am__quote@ @@ -556,6 +559,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tre-parse.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tre-stack.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tre.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uri.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf8.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xma.Plo@am__quote@ diff --git a/qse/lib/cmn/alg-base64.c b/qse/lib/cmn/alg-base64.c new file mode 100644 index 00000000..ffe2b3e2 --- /dev/null +++ b/qse/lib/cmn/alg-base64.c @@ -0,0 +1,109 @@ +/* + * $Id$ + * + Copyright 2006-2012 Chung, Hyung-Hwan. + This file is part of QSE. + + QSE is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + QSE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with QSE. If not, see . + */ + +#include + +#define ENC(x) \ + ((x < 26)? (QSE_MT('A') + x): \ + (x < 52)? (QSE_MT('a') + (x - 26)): \ + (x < 62)? (QSE_MT('0') + (x - 52)): \ + (x == 62)? QSE_MT('+'): QSE_MT('/')) + +#define DEC(x) \ + ((x >= QSE_MT('A') && x <= QSE_MT('Z'))? (x - QSE_MT('A')): \ + (x >= QSE_MT('a') && x <= QSE_MT('z'))? (x - QSE_MT('a') + 26): \ + (x >= QSE_MT('0') && x <= QSE_MT('9'))? (x - QSE_MT('0') + 52): \ + (x == QSE_MT('+'))? 62: 63) + +qse_size_t qse_enbase64 ( + const qse_uint8_t* in, qse_size_t isz, + qse_mchar_t* out, qse_size_t osz, qse_size_t* xsz) +{ + qse_size_t idx = 0, idx2 = 0, i; + + /* 3 8-bit values to 4 6-bit values */ + + for (i = 0; i < isz; i += 3) + { + qse_uint8_t b1, b2, b3; + qse_uint8_t c1, c2, c3, c4; + + b1 = in[i]; + b2 = (i + 1 < isz)? in[i + 1]: 0; + b3 = (i + 2 < isz)? in[i + 2]: 0; + + c1 = b1 >> 2; + c2 = ((b1 & 0x03) << 4) | (b2 >> 4); + c3 = ((b2 & 0x0F) << 2) | (b3 >> 6); + c4 = b3 & 0x3F; + + if (idx + 3 < osz) + { + out[idx++] = ENC(c1); + out[idx++] = ENC(c2); + out[idx++] = (i + 1 < isz)? ENC(c3): QSE_MT('='); + out[idx++] = (i + 2 < isz)? ENC(c4): QSE_MT('='); + } + idx2 += 4; + } + + if (xsz) *xsz = idx2; + return idx; +} + +qse_size_t qse_debase64 ( + const qse_mchar_t* in, qse_size_t isz, + qse_uint8_t* out, qse_size_t osz, qse_size_t* xsz) +{ + qse_size_t idx = 0, idx2 = 0, i; + + for (i = 0; i < isz; i += 4) + { + qse_uint8_t c1, c2, c3, c4; + qse_uint8_t b1, b2, b3, b4; + + c1 = in[i]; + c2 = (i + 1 < isz)? in[i + 1]: QSE_MT('A'); + c3 = (i + 2 < isz)? in[i + 2]: QSE_MT('A'); + c4 = (i + 3 < isz)? in[i + 3]: QSE_MT('A'); + + b1 = DEC(c1); + b2 = DEC(c2); + b3 = DEC(c3); + b4 = DEC(c4); + + idx2++; + if (idx < osz) out[idx++] = (b1 << 2) | (b2 >> 4); + + if (c3 != QSE_MT('=')) + { + idx2++; + if (idx < osz) out[idx++] = ((b2 & 0x0F) << 4) | (b3 >> 2); + } + if (c4 != QSE_MT('=')) + { + idx2++; + if (idx < osz) out[idx++] = ((b3 & 0x03) << 6) | b4; + } + } + + if (xsz) *xsz = idx2; + return idx; +} diff --git a/qse/lib/cmn/dll.c b/qse/lib/cmn/dll.c index 39b8d164..56604f29 100644 --- a/qse/lib/cmn/dll.c +++ b/qse/lib/cmn/dll.c @@ -60,6 +60,7 @@ qse_dll_t* qse_dll_open (qse_mmgr_t* mmgr, qse_size_t xtnsize) return QSE_NULL; } + QSE_MEMSET (dll + 1, 0, xtnsize); return dll; } @@ -71,7 +72,7 @@ void qse_dll_close (qse_dll_t* dll) int qse_dll_init (qse_dll_t* dll, qse_mmgr_t* mmgr) { - /* do not zero out the xtnsizeension */ + /* do not zero out the extension */ QSE_MEMSET (dll, 0, QSE_SIZEOF(*dll)); dll->mmgr = mmgr; diff --git a/qse/lib/cmn/env.c b/qse/lib/cmn/env.c index 5f08faa5..6e743ea7 100644 --- a/qse/lib/cmn/env.c +++ b/qse/lib/cmn/env.c @@ -50,6 +50,7 @@ qse_env_t* qse_env_open (qse_mmgr_t* mmgr, qse_size_t xtnsize, int fromcurenv) return QSE_NULL; } + QSE_MEMSET (env + 1, 0, xtnsize); return env; } diff --git a/qse/lib/cmn/fma.c b/qse/lib/cmn/fma.c index 27da0b08..22781e47 100644 --- a/qse/lib/cmn/fma.c +++ b/qse/lib/cmn/fma.c @@ -38,6 +38,7 @@ qse_fma_t* qse_fma_open ( return QSE_NULL; } + QSE_MEMSET (fma + 1, 0, xtnsize); return fma; } diff --git a/qse/lib/cmn/fs.c b/qse/lib/cmn/fs.c index 7d27a78e..4745f614 100644 --- a/qse/lib/cmn/fs.c +++ b/qse/lib/cmn/fs.c @@ -67,6 +67,7 @@ qse_fs_t* qse_fs_open (qse_mmgr_t* mmgr, qse_size_t xtnsize) return QSE_NULL; } + QSE_MEMSET (fs + 1, 0, xtnsize); return fs; } diff --git a/qse/lib/cmn/htb.c b/qse/lib/cmn/htb.c index 2f9abe42..00859c2a 100644 --- a/qse/lib/cmn/htb.c +++ b/qse/lib/cmn/htb.c @@ -274,6 +274,7 @@ htb_t* qse_htb_open ( return QSE_NULL; } + QSE_MEMSET (htb + 1, 0, xtnsize); return htb; } diff --git a/qse/lib/cmn/mbwc-str.c b/qse/lib/cmn/mbwc-str.c index 23671c59..3ac16bf4 100644 --- a/qse/lib/cmn/mbwc-str.c +++ b/qse/lib/cmn/mbwc-str.c @@ -489,6 +489,21 @@ qse_mchar_t* qse_wcstombsdupwithcmgr (const qse_wchar_t* wcs, qse_mmgr_t* mmgr, return mbs; } +qse_mchar_t* qse_wcsntombsdupwithcmgr (const qse_wchar_t* wcs, qse_size_t len, qse_mmgr_t* mmgr, qse_cmgr_t* cmgr) +{ + qse_size_t mbslen; + qse_mchar_t* mbs; + + if (qse_wcsntombsnwithcmgr (wcs, &len, QSE_NULL, &mbslen, cmgr) <= -1) return QSE_NULL; + + mbs = QSE_MMGR_ALLOC (mmgr, (mbslen + 1) * QSE_SIZEOF(*mbs)); + if (mbs == QSE_NULL) return QSE_NULL; + + qse_wcsntombsnwithcmgr (wcs, &len, mbs, &mbslen, cmgr); + mbs[mbslen] = QSE_MT('\0'); + return mbs; +} + qse_mchar_t* qse_wcsatombsdupwithcmgr (const qse_wchar_t* wcs[], qse_mmgr_t* mmgr, qse_cmgr_t* cmgr) { qse_mchar_t* buf, * ptr; diff --git a/qse/lib/cmn/mbwc.c b/qse/lib/cmn/mbwc.c index 9c2f06cb..d5495537 100644 --- a/qse/lib/cmn/mbwc.c +++ b/qse/lib/cmn/mbwc.c @@ -212,6 +212,11 @@ qse_mchar_t* qse_wcstombsdup (const qse_wchar_t* wcs, qse_mmgr_t* mmgr) return qse_wcstombsdupwithcmgr (wcs, mmgr, dfl_cmgr); } +qse_mchar_t* qse_wcsntombsdup (const qse_wchar_t* wcs, qse_size_t len, qse_mmgr_t* mmgr) +{ + return qse_wcsntombsdupwithcmgr (wcs, len, mmgr, dfl_cmgr); +} + qse_mchar_t* qse_wcsatombsdup (const qse_wchar_t* wcs[], qse_mmgr_t* mmgr) { return qse_wcsatombsdupwithcmgr (wcs, mmgr, dfl_cmgr); diff --git a/qse/lib/cmn/nwio.c b/qse/lib/cmn/nwio.c index bee8dbb6..34232dfe 100644 --- a/qse/lib/cmn/nwio.c +++ b/qse/lib/cmn/nwio.c @@ -343,6 +343,7 @@ qse_nwio_t* qse_nwio_open ( return QSE_NULL; } + QSE_MEMSET (nwio + 1, 0, xtnsize); return nwio; } diff --git a/qse/lib/cmn/oht.c b/qse/lib/cmn/oht.c index de1569bc..2f730c7e 100644 --- a/qse/lib/cmn/oht.c +++ b/qse/lib/cmn/oht.c @@ -57,6 +57,7 @@ qse_oht_t* qse_oht_open ( return QSE_NULL; } + QSE_MEMSET (oht + 1, 0, xtnsize); return oht; } diff --git a/qse/lib/cmn/pma.c b/qse/lib/cmn/pma.c index 3f0fe063..90754c03 100644 --- a/qse/lib/cmn/pma.c +++ b/qse/lib/cmn/pma.c @@ -62,6 +62,7 @@ qse_pma_t* qse_pma_open (qse_mmgr_t* mmgr, qse_size_t xtnsize) return QSE_NULL; } + QSE_MEMSET (pma + 1, 0, xtnsize); return pma; } diff --git a/qse/lib/cmn/rbt.c b/qse/lib/cmn/rbt.c index 27175484..c59d809c 100644 --- a/qse/lib/cmn/rbt.c +++ b/qse/lib/cmn/rbt.c @@ -210,6 +210,7 @@ rbt_t* qse_rbt_open (mmgr_t* mmgr, size_t xtnsize, int kscale, int vscale) return QSE_NULL; } + QSE_MEMSET (rbt + 1, 0, xtnsize); return rbt; } diff --git a/qse/lib/cmn/sio.c b/qse/lib/cmn/sio.c index 9aff823e..c2ea0b31 100644 --- a/qse/lib/cmn/sio.c +++ b/qse/lib/cmn/sio.c @@ -106,6 +106,7 @@ qse_sio_t* qse_sio_open ( return QSE_NULL; } + QSE_MEMSET (sio + 1, 0, xtnsize); return sio; } diff --git a/qse/lib/cmn/str-cmp.c b/qse/lib/cmn/str-cmp.c index 924ea60e..2c473f92 100644 --- a/qse/lib/cmn/str-cmp.c +++ b/qse/lib/cmn/str-cmp.c @@ -130,6 +130,21 @@ int qse_mbszcmp (const qse_mchar_t* s1, const qse_mchar_t* s2, qse_size_t n) return (*s1 > *s2)? 1: -1; } +int qse_mbszcasecmp (const qse_mchar_t* s1, const qse_mchar_t* s2, qse_size_t n) +{ + if (n == 0) return 0; + + while (QSE_TOMUPPER(*s1) == QSE_TOMUPPER(*s2)) + { + if (*s1 == QSE_MT('\0') || n == 1) return 0; + s1++, s2++, n--; + } + + return (QSE_TOMUPPER(*s1) > QSE_TOMUPPER(*s2))? 1: -1; +} + +/* ------------------------------------------------------------- */ + int qse_wcscmp (const qse_wchar_t* s1, const qse_wchar_t* s2) { while (*s1 == *s2) @@ -237,3 +252,16 @@ int qse_wcszcmp (const qse_wchar_t* s1, const qse_wchar_t* s2, qse_size_t n) return (*s1 > *s2)? 1: -1; } + +int qse_wcszcasecmp (const qse_wchar_t* s1, const qse_wchar_t* s2, qse_size_t n) +{ + if (n == 0) return 0; + + while (QSE_TOWUPPER(*s1) == QSE_TOWUPPER(*s2)) + { + if (*s1 == QSE_WT('\0') || n == 1) return 0; + s1++, s2++, n--; + } + + return (QSE_TOWUPPER(*s1) > QSE_TOWUPPER(*s2))? 1: -1; +} diff --git a/qse/lib/cmn/str-dup.c b/qse/lib/cmn/str-dup.c index b5ffa5fe..ea611828 100644 --- a/qse/lib/cmn/str-dup.c +++ b/qse/lib/cmn/str-dup.c @@ -91,6 +91,25 @@ qse_mchar_t* qse_mbsadup (const qse_mchar_t* str[], qse_mmgr_t* mmgr) return buf; } +qse_mchar_t* qse_mbsxadup (const qse_mcstr_t str[], qse_mmgr_t* mmgr) +{ + qse_mchar_t* buf, * ptr; + qse_size_t i; + qse_size_t capa = 0; + + QSE_ASSERT (mmgr != QSE_NULL); + + for (i = 0; str[i].ptr; i++) capa += str[i].len; + + buf = (qse_mchar_t*) QSE_MMGR_ALLOC (mmgr, (capa+1)*QSE_SIZEOF(*buf)); + if (buf == QSE_NULL) return QSE_NULL; + + ptr = buf; + for (i = 0; str[i].ptr; i++) ptr += qse_mbsncpy (ptr, str[i].ptr, str[i].len); + + return buf; +} + /* --------------------------------------------------------------- */ qse_wchar_t* qse_wcsdup (const qse_wchar_t* str, qse_mmgr_t* mmgr) @@ -165,3 +184,21 @@ qse_wchar_t* qse_wcsadup (const qse_wchar_t* str[], qse_mmgr_t* mmgr) return buf; } +qse_wchar_t* qse_wcsxadup (const qse_wcstr_t str[], qse_mmgr_t* mmgr) +{ + qse_wchar_t* buf, * ptr; + qse_size_t i; + qse_size_t capa = 0; + + QSE_ASSERT (mmgr != QSE_NULL); + + for (i = 0; str[i].ptr; i++) capa += str[i].len; + + buf = (qse_wchar_t*) QSE_MMGR_ALLOC (mmgr, (capa+1)*QSE_SIZEOF(*buf)); + if (buf == QSE_NULL) return QSE_NULL; + + ptr = buf; + for (i = 0; str[i].ptr; i++) ptr += qse_wcsncpy (ptr, str[i].ptr, str[i].len); + + return buf; +} diff --git a/qse/lib/cmn/tio.c b/qse/lib/cmn/tio.c index e9e324dc..59263ba3 100644 --- a/qse/lib/cmn/tio.c +++ b/qse/lib/cmn/tio.c @@ -45,6 +45,7 @@ qse_tio_t* qse_tio_open (qse_mmgr_t* mmgr, qse_size_t xtnsize, int flags) return QSE_NULL; } + QSE_MEMSET (tio + 1, 0, xtnsize); return tio; } diff --git a/qse/lib/cmn/tre.c b/qse/lib/cmn/tre.c index e227641d..d2ec73a9 100644 --- a/qse/lib/cmn/tre.c +++ b/qse/lib/cmn/tre.c @@ -37,6 +37,7 @@ qse_tre_t* qse_tre_open (qse_mmgr_t* mmgr, qse_size_t xtnsize) return QSE_NULL; } + QSE_MEMSET (tre + 1, 0, xtnsize); return tre; } diff --git a/qse/lib/cmn/uri.c b/qse/lib/cmn/uri.c index ef46fe3a..79175afe 100644 --- a/qse/lib/cmn/uri.c +++ b/qse/lib/cmn/uri.c @@ -1,104 +1,268 @@ +/* + * $Id$ + * + Copyright 2006-2012 Chung, Hyung-Hwan. + This file is part of QSE. -static int qse_ripuri (qse_httpd_t* httpd, const qse_char_t* uri, int flags) + QSE is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + QSE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with QSE. If not, see . + */ + +#include +#include "mem.h" + +int qse_mbstouri (const qse_mchar_t* str, qse_uri_t* uri, int flags) { - const qse_char_t* ptr, * colon, * at; - qse_size_t len; + const qse_mchar_t* ptr, * colon; qse_uri_t xuri; - QSE_MEMSET (xuri, 0, QSE_SIZEOF(xuri)); + QSE_MEMSET (&xuri, 0, QSE_SIZEOF(xuri)); /* scheme */ - xuri.scheme.ptr = ptr; - while (*uri != QSE_T(':')) + xuri.scheme.ptr = str; + while (*str != QSE_MT(':')) { - if (*uri == QSE_T('\0')) return -1; - uri++; + if (*str == QSE_MT('\0')) return -1; + str++; } - xuri.scheme.len = uri - xuri.scheme.ptr; + xuri.scheme.len = str - (const qse_mchar_t*)xuri.scheme.ptr; - uri++; /* skip : */ - if (*uri != QSE_T('/')) return -1; - uri++; /* skip / */ - if (*uri != QSE_T('/')) return -1; - uri++; /* skip / */ + str++; /* skip : */ + if (*str != QSE_MT('/')) return -1; + str++; /* skip / */ + if (*str != QSE_MT('/')) return -1; + str++; /* skip / */ /* username, password, host, port */ - for (colon = QSE_NULL, at = QSE_NULL, ptr = uri; ; uri++) + for (colon = QSE_NULL, ptr = str; ; str++) { - if (at == QSE_NULL) + if (flags & QSE_MBSTOURI_NOAUTH) { - if (colon == QSE_NULL && *uri == QSE_T(':')) colon = uri; - else if (*uri == QSE_T('@')) - { - if (colon) - { - xuri.user.ptr = ptr; - xuri.user.len = colon - ptr; - xuri.pass.ptr = colon + 1; - xuri.pass.len = uri - colon - 1; - - colon = QSE_NULL; - } - else - { - xuri.user.ptr = ptr; - xuri.user.len = uri - ptr; - } - } - else if (*uri == QSE_T('/') || *uri == QSE_T('\0')) - { - xuri.host = xuri.user; - xuir.port = xuri.pass; - - xuri.user.ptr = QSE_NULL; - xuri.user.len = 0; - xuri.pass.ptr = QSE_NULL; - xuri.pass.len = 0; - break; - } - } - else - { - if (colon == QSE_NULL && *uri == QSE_T(':')) colon = uri; - else if (*uri == QSE_T('/') || *uri == QSE_T('\0')) + if (colon == QSE_NULL && *str == QSE_MT(':')) colon = str; + else if (*str == QSE_MT('/') || *str == QSE_MT('\0')) { if (colon) { xuri.host.ptr = ptr; xuri.host.len = colon - ptr; xuri.port.ptr = colon + 1; - xuri.port.len = uri - colon - 1; + xuri.port.len = str - colon - 1; } else { xuri.host.ptr = ptr; - xuri.host.len = uri - ptr; + xuri.host.len = str - ptr; } + break; } } - } - - if (uri == QSE_T('/')) - { - xuri.path.ptr = uri; - while (*uri != QSE_T('\0') && *uri != QSE_T('?')) uri++; - xuri.path.len = uri - xuri.path.ptr; - - if (uri == QSE('#')) + else { - xuri.query.ptr = ++uri; - while (*uri != QSE_T('\0') && *uri != QSE_T('#')) uri++; - xuri.query.len = uri - xuri.query.ptr; - - if (uri == QSE_T('#')) + if (colon == QSE_NULL && *str == QSE_MT(':')) colon = str; + else if (xuri.auth.user.ptr == QSE_NULL && *str == QSE_MT('@')) { - xuri.query.ptr = ++uri; - while (*uri != QSE_T('\0')) uri++; - xuri.fragment.len = uri - xuri.fragment.ptr; + if (colon) + { + xuri.auth.user.ptr = ptr; + xuri.auth.user.len = colon - ptr; + xuri.auth.pass.ptr = colon + 1; + xuri.auth.pass.len = str - colon - 1; + + colon = QSE_NULL; + } + else + { + xuri.auth.user.ptr = ptr; + xuri.auth.user.len = str - ptr; + } + + ptr = str + 1; + } + else if (*str == QSE_MT('/') || *str == QSE_MT('\0')) + { + if (colon) + { + xuri.host.ptr = ptr; + xuri.host.len = colon - ptr; + xuri.port.ptr = colon + 1; + xuri.port.len = str - colon - 1; + } + else + { + xuri.host.ptr = ptr; + xuri.host.len = str - ptr; + } + + break; } } } - *xuri = scheme; + if (*str == QSE_MT('/')) + { + xuri.path.ptr = str; + while (*str != QSE_MT('\0')) + { + if ((!(flags & QSE_MBSTOURI_NOQUERY) && *str == QSE_MT('?')) || + (!(flags & QSE_MBSTOURI_NOFRAG) && *str == QSE_MT('#'))) break; + str++; + } + xuri.path.len = str - (const qse_mchar_t*)xuri.path.ptr; + + if (!(flags & QSE_MBSTOURI_NOQUERY) && *str == QSE_MT('?')) + { + xuri.query.ptr = ++str; + while (*str != QSE_MT('\0')) + { + if (!(flags & QSE_MBSTOURI_NOFRAG) && *str == QSE_MT('#')) break; + str++; + } + xuri.query.len = str - (const qse_mchar_t*)xuri.query.ptr; + } + + if (!(flags & QSE_MBSTOURI_NOFRAG) && *str == QSE_MT('#')) + { + xuri.frag.ptr = ++str; + while (*str != QSE_MT('\0')) str++; + xuri.frag.len = str - (const qse_mchar_t*)xuri.frag.ptr; + } + } + + QSE_ASSERT (*str == QSE_MT('\0')); + *uri = xuri; + return 0; +} + +/* -------------------------------------------------------- */ + +int qse_wcstouri (const qse_wchar_t* str, qse_uri_t* uri, int flags) +{ + const qse_wchar_t* ptr, * colon; + qse_uri_t xuri; + + QSE_MEMSET (&xuri, 0, QSE_SIZEOF(xuri)); + + /* scheme */ + xuri.scheme.ptr = str; + while (*str != QSE_WT(':')) + { + if (*str == QSE_WT('\0')) return -1; + str++; + } + xuri.scheme.len = str - (const qse_wchar_t*)xuri.scheme.ptr; + + str++; /* skip : */ + if (*str != QSE_WT('/')) return -1; + str++; /* skip / */ + if (*str != QSE_WT('/')) return -1; + str++; /* skip / */ + + /* username, password, host, port */ + for (colon = QSE_NULL, ptr = str; ; str++) + { + if (flags & QSE_WCSTOURI_NOAUTH) + { + if (colon == QSE_NULL && *str == QSE_WT(':')) colon = str; + else if (*str == QSE_WT('/') || *str == QSE_WT('\0')) + { + if (colon) + { + xuri.host.ptr = ptr; + xuri.host.len = colon - ptr; + xuri.port.ptr = colon + 1; + xuri.port.len = str - colon - 1; + } + else + { + xuri.host.ptr = ptr; + xuri.host.len = str - ptr; + } + break; + } + } + else + { + if (colon == QSE_NULL && *str == QSE_WT(':')) colon = str; + else if (xuri.auth.user.ptr == QSE_NULL && *str == QSE_WT('@')) + { + if (colon) + { + xuri.auth.user.ptr = ptr; + xuri.auth.user.len = colon - ptr; + xuri.auth.pass.ptr = colon + 1; + xuri.auth.pass.len = str - colon - 1; + + colon = QSE_NULL; + } + else + { + xuri.auth.user.ptr = ptr; + xuri.auth.user.len = str - ptr; + } + + ptr = str + 1; + } + else if (*str == QSE_WT('/') || *str == QSE_WT('\0')) + { + if (colon) + { + xuri.host.ptr = ptr; + xuri.host.len = colon - ptr; + xuri.port.ptr = colon + 1; + xuri.port.len = str - colon - 1; + } + else + { + xuri.host.ptr = ptr; + xuri.host.len = str - ptr; + } + + break; + } + } + } + + if (*str == QSE_WT('/')) + { + xuri.path.ptr = str; + while (*str != QSE_WT('\0')) + { + if ((!(flags & QSE_WCSTOURI_NOQUERY) && *str == QSE_WT('?')) || + (!(flags & QSE_WCSTOURI_NOFRAG) && *str == QSE_WT('#'))) break; + str++; + } + xuri.path.len = str - (const qse_wchar_t*)xuri.path.ptr; + + if (!(flags & QSE_WCSTOURI_NOQUERY) && *str == QSE_WT('?')) + { + xuri.query.ptr = ++str; + while (*str != QSE_WT('\0')) + { + if (!(flags & QSE_WCSTOURI_NOFRAG) && *str == QSE_WT('#')) break; + str++; + } + xuri.query.len = str - (const qse_wchar_t*)xuri.query.ptr; + } + + if (!(flags & QSE_WCSTOURI_NOFRAG) && *str == QSE_WT('#')) + { + xuri.frag.ptr = ++str; + while (*str != QSE_WT('\0')) str++; + xuri.frag.len = str - (const qse_wchar_t*)xuri.frag.ptr; + } + } + + QSE_ASSERT (*str == QSE_WT('\0')); + *uri = xuri; return 0; } diff --git a/qse/lib/cmn/xma.c b/qse/lib/cmn/xma.c index c8190a3d..9403859c 100644 --- a/qse/lib/cmn/xma.c +++ b/qse/lib/cmn/xma.c @@ -118,6 +118,7 @@ qse_xma_t* qse_xma_open ( return QSE_NULL; } + QSE_MEMSET (xma + 1, 0, xtnsize); return xma; } diff --git a/qse/lib/net/httpd-std.c b/qse/lib/net/httpd-std.c index a4033cc8..88d230cb 100644 --- a/qse/lib/net/httpd-std.c +++ b/qse/lib/net/httpd-std.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #if defined(_WIN32) # include @@ -68,7 +70,13 @@ struct server_xtn_t { - qse_mxstr_t docroot; +#define CFG_DOCROOT 0 +#define CFG_REALM 1 +#define CFG_USERNAME 2 +#define CFG_PASSWORD 3 +#define CFG_BASICAUTH 4 +#define CFG_BASICAUTH_B64 5 + qse_mxstr_t cfg[6]; }; typedef struct server_xtn_t server_xtn_t; @@ -421,132 +429,143 @@ void* qse_httpd_getxtnstd (qse_httpd_t* httpd) return (void*)((httpd_xtn_t*)QSE_XTN(httpd) + 1); } -static int parse_server_uri ( - qse_httpd_t* httpd, const qse_char_t* uri, - qse_httpd_server_t* server, const qse_char_t** docroot) -{ - qse_uint16_t default_port; - qse_cstr_t tmp; - - server->flags = 0; - - /* check the protocol part */ - tmp.ptr = uri; - while (*uri != QSE_T(':')) - { - if (*uri == QSE_T('\0')) - { - httpd->errnum = QSE_HTTPD_EINVAL; - return -1; - } - uri++; - } - tmp.len = uri - tmp.ptr; - if (qse_strxcmp (tmp.ptr, tmp.len, QSE_T("http")) == 0) - { - default_port = DEFAULT_PORT; - } - else if (qse_strxcmp (tmp.ptr, tmp.len, QSE_T("https")) == 0) - { - server->flags |= QSE_HTTPD_SERVER_SECURE; - default_port = DEFAULT_SECURE_PORT; - } - else - { - httpd->errnum = QSE_HTTPD_EINVAL; - return -1; - } - - uri++; /* skip : */ - if (*uri != QSE_T('/')) - { - httpd->errnum = QSE_HTTPD_EINVAL; - return -1; - } - uri++; /* skip / */ - if (*uri != QSE_T('/')) - { - httpd->errnum = QSE_HTTPD_EINVAL; - return -1; - } - uri++; /* skip / */ - - - tmp.ptr = uri; - while (*uri != QSE_T('\0') && *uri != QSE_T('/')) uri++; - tmp.len = uri - tmp.ptr; - - if (qse_strntonwad (tmp.ptr, tmp.len, &server->nwad) <= -1) - { - httpd->errnum = QSE_HTTPD_EINVAL; - return -1; - } - - *docroot = uri; - - if (server->nwad.type == QSE_NWAD_IN4) - { - if (server->nwad.u.in4.port == 0) - server->nwad.u.in4.port = qse_hton16(default_port); - } - else if (server->nwad.type == QSE_NWAD_IN6) - { - if (server->nwad.u.in6.port == 0) - server->nwad.u.in6.port = qse_hton16(default_port); - } - - return 0; -} - static void predetach_server (qse_httpd_t* httpd, qse_httpd_server_t* server) { server_xtn_t* server_xtn; + qse_size_t i; server_xtn = (server_xtn_t*) qse_httpd_getserverxtn (httpd, server); - if (server_xtn->docroot.ptr) + + for (i = QSE_COUNTOF(server_xtn->cfg); i > 0; ) { - QSE_MMGR_FREE (httpd->mmgr, server_xtn->docroot.ptr); - server_xtn->docroot.ptr = QSE_NULL; - server_xtn->docroot.len = 0; + i--; + if (server_xtn->cfg[i].ptr) + { + QSE_MMGR_FREE (httpd->mmgr, server_xtn->cfg[i].ptr); + server_xtn->cfg[i].ptr = QSE_NULL; + server_xtn->cfg[i].len = 0; + } } } qse_httpd_server_t* qse_httpd_attachserverstd ( qse_httpd_t* httpd, const qse_char_t* uri, qse_size_t xtnsize) { - qse_httpd_server_t server, * xserver; - const qse_char_t* docroot; + qse_httpd_server_t server; + qse_httpd_server_t* xserver; server_xtn_t* server_xtn; + qse_mcstr_t tmp[4]; - if (parse_server_uri (httpd, uri, &server, &docroot) <= -1) return QSE_NULL; - server.predetach = predetach_server; + qse_uint16_t default_port; + qse_size_t i; + qse_uri_t xuri; - xserver = qse_httpd_attachserver ( - httpd, &server, QSE_SIZEOF(*server_xtn) + xtnsize); - if (xserver == QSE_NULL) return QSE_NULL; + QSE_MEMSET (&server, 0, QSE_SIZEOF(server)); - if (docroot[0] == QSE_T('/') && docroot[1] != QSE_T('\0')) + if (qse_strtouri (uri, &xuri, QSE_STRTOURI_NOQUERY) <= -1) goto invalid; + + if (qse_strxcmp (xuri.scheme.ptr, xuri.scheme.len, QSE_T("http")) == 0) { - server_xtn = qse_httpd_getserverxtn (httpd, xserver); + default_port = DEFAULT_PORT; + } + else if (qse_strxcmp (xuri.scheme.ptr, xuri.scheme.len, QSE_T("https")) == 0) + { + server.flags |= QSE_HTTPD_SERVER_SECURE; + default_port = DEFAULT_SECURE_PORT; + } + else goto invalid; -#if defined(QSE_CHAR_IS_MCHAR) - server_xtn->docroot.ptr = qse_mbsdup (docroot, httpd->mmgr); -#else - server_xtn->docroot.ptr = qse_wcstombsdup (docroot, httpd->mmgr); -#endif - if (server_xtn->docroot.ptr == QSE_NULL) - { - qse_httpd_detachserver (httpd, xserver); - httpd->errnum = QSE_HTTPD_ENOMEM; - return QSE_NULL; - } + if (qse_strntonwad ( + xuri.host.ptr, + xuri.host.len + (xuri.port.ptr? (xuri.port.len + 1): 0), + &server.nwad) <= -1) goto invalid; - server_xtn->docroot.len = qse_mbslen(server_xtn->docroot.ptr); + if (server.nwad.type == QSE_NWAD_IN4) + { + if (server.nwad.u.in4.port == 0) + server.nwad.u.in4.port = qse_hton16(default_port); + } + else if (server.nwad.type == QSE_NWAD_IN6) + { + if (server.nwad.u.in6.port == 0) + server.nwad.u.in6.port = qse_hton16(default_port); } + server.predetach = predetach_server; + xserver = qse_httpd_attachserver (httpd, &server, QSE_SIZEOF(*server_xtn) + xtnsize); + if (xserver == QSE_NULL) return QSE_NULL; + + server_xtn = qse_httpd_getserverxtn (httpd, xserver); + +#if defined(QSE_CHAR_IS_MCHAR) + if (xuri.path.ptr) server_xtn->cfg[CFG_DOCROOT].ptr = qse_mbsxdup (xuri.path.ptr, xuri.path.len, httpd->mmgr); + if (xuri.auth.user.ptr) server_xtn->cfg[CFG_USERNAME].ptr = qse_mbsxdup (xuri.auth.user.ptr, xuri.auth.user.len, httpd->mmgr); + if (xuri.auth.pass.ptr) server_xtn->cfg[CFG_PASSWORD].ptr = qse_mbsxdup (xuri.auth.pass.ptr, xuri.auth.pass.len, httpd->mmgr); + if (xuri.frag.ptr) server_xtn->cfg[CFG_REALM].ptr = qse_mbsxdup (xuri.frag.ptr, xuri.frag.len, httpd->mmgr); + +#else + if (xuri.path.ptr) server_xtn->cfg[CFG_DOCROOT].ptr = qse_wcsntombsdup (xuri.path.ptr, xuri.path.len, httpd->mmgr); + if (xuri.auth.user.ptr) server_xtn->cfg[CFG_USERNAME].ptr = qse_wcsntombsdup (xuri.auth.user.ptr, xuri.auth.user.len, httpd->mmgr); + if (xuri.auth.pass.ptr) server_xtn->cfg[CFG_PASSWORD].ptr = qse_wcsntombsdup (xuri.auth.pass.ptr, xuri.auth.pass.len, httpd->mmgr); + if (xuri.frag.ptr) server_xtn->cfg[CFG_REALM].ptr = qse_wcsntombsdup (xuri.frag.ptr, xuri.frag.len, httpd->mmgr); + +#endif + if ((xuri.path.ptr && !server_xtn->cfg[CFG_DOCROOT].ptr) || + (xuri.auth.user.ptr && !server_xtn->cfg[CFG_USERNAME].ptr) || + (xuri.auth.pass.ptr && !server_xtn->cfg[CFG_PASSWORD].ptr) || + (xuri.frag.ptr && !server_xtn->cfg[CFG_REALM].ptr)) goto nomem_after_attach; + + for (i = 0; i < QSE_COUNTOF(server_xtn->cfg); i++) + { + if (server_xtn->cfg[i].ptr) + server_xtn->cfg[i].len = qse_mbslen(server_xtn->cfg[i].ptr); + } + + tmp[0].ptr = server_xtn->cfg[CFG_USERNAME].ptr? server_xtn->cfg[CFG_USERNAME].ptr: QSE_MT(""); + tmp[0].len = server_xtn->cfg[CFG_USERNAME].len; + tmp[1].ptr = QSE_MT(":"); + tmp[1].len = 1; + tmp[2].ptr = server_xtn->cfg[CFG_PASSWORD].ptr? server_xtn->cfg[CFG_PASSWORD].ptr: QSE_MT(""); + tmp[2].len = server_xtn->cfg[CFG_PASSWORD].len; + tmp[3].ptr = QSE_NULL; + tmp[3].len = 0; + + server_xtn->cfg[CFG_BASICAUTH].ptr = qse_mbsxadup (tmp, httpd->mmgr); + if (!server_xtn->cfg[CFG_BASICAUTH].ptr) goto nomem_after_attach; + server_xtn->cfg[CFG_BASICAUTH].len = qse_mbslen (server_xtn->cfg[CFG_BASICAUTH].ptr); + + server_xtn->cfg[CFG_BASICAUTH_B64].len = ((server_xtn->cfg[CFG_BASICAUTH].len / 3) + 1) * 4; + server_xtn->cfg[CFG_BASICAUTH_B64].ptr = QSE_MMGR_ALLOC ( + httpd->mmgr, + (server_xtn->cfg[CFG_BASICAUTH_B64].len + 1) * QSE_SIZEOF(qse_mchar_t)); + if (!server_xtn->cfg[CFG_BASICAUTH_B64].ptr) goto nomem_after_attach; + + qse_enbase64 ( + server_xtn->cfg[CFG_BASICAUTH].ptr, + server_xtn->cfg[CFG_BASICAUTH].len, + server_xtn->cfg[CFG_BASICAUTH_B64].ptr, + server_xtn->cfg[CFG_BASICAUTH_B64].len, + &server_xtn->cfg[CFG_BASICAUTH_B64].len + ); + server_xtn->cfg[CFG_BASICAUTH_B64].ptr[server_xtn->cfg[CFG_BASICAUTH_B64].len] = QSE_MT('\0'); + return xserver; + +invalid: + httpd->errnum = QSE_HTTPD_EINVAL; + return QSE_NULL; + +nomem_after_attach: + qse_httpd_detachserver (httpd, xserver); + httpd->errnum = QSE_HTTPD_ENOMEM; + return QSE_NULL; } +void* qse_httpd_getserverxtnstd (qse_httpd_t* httpd, qse_httpd_server_t* server) +{ + server_xtn_t* xtn = qse_httpd_getserverxtn (httpd, server); + return (void*)(xtn + 1); +} /* ------------------------------------------------------------------- */ union sockaddr_t @@ -1589,36 +1608,6 @@ if (qse_htre_getcontentlen(req) > 0) } if (task == QSE_NULL) goto oops; } - -#if 0 - if (peek) - { - const qse_htre_hdrval_t* auth; - int authorized = 0; - - auth = qse_htre_getheaderval (req, QSE_MT("Authorization")); - if (auth) - { - /* TODO: PERFORM authorization... */ - /* BASE64 decode... */ - while (auth->next) auth = auth->next; - authorized = 1; - } - - if (authorized) - { - /* nph-cgi */ - task = qse_httpd_entasknph ( - httpd, client, QSE_NULL, qpath, req); - } - else - { - task = qse_httpd_entaskauth ( - httpd, client, QSE_NULL, QSE_MT("Secure Area"), req); - } - if (task == QSE_NULL) goto oops; - } -#endif } else { @@ -1654,27 +1643,6 @@ static int proxy_request ( { qse_httpd_task_t* task; -#if 0 - const qse_mchar_t* qpath; - - qpath = qse_htre_qpathptr (eq); - if (qpath[0] == QSE_MT('/')) - { - host = qse_htre_getheaderval (req, QSE_MT("Host")); - if (host == QSE_NULL) - { -qse_printf (QSE_T("Host not included....\n")); - goto oops; - } - } - else - { - const qse_mchar_t* host; - qse_parseuri (); - } -#endif - - /* TODO: investigate if the proxy need to handle 100-continue */ if (peek) @@ -1866,12 +1834,33 @@ target->u.proxy.src.u.in4.port = 0; return 0; #endif - if (server_xtn->docroot.ptr || qpath[0] != QSE_MT('/')) + if (server_xtn->cfg[CFG_REALM].ptr && server_xtn->cfg[CFG_BASICAUTH_B64].ptr) + { + const qse_htre_hdrval_t* auth; + + auth = qse_htre_getheaderval (req, QSE_MT("Authorization")); + if (auth) + { + while (auth->next) auth = auth->next; + + if (qse_mbszcasecmp(auth->ptr, QSE_MT("Basic "), 6) == 0) + { + if (qse_mbscmp (&auth->ptr[6], server_xtn->cfg[CFG_BASICAUTH_B64].ptr) == 0) goto auth_ok; + } + } + + target->type = QSE_HTTPD_RSRC_AUTH; + target->u.auth.realm = server_xtn->cfg[CFG_REALM].ptr; + return 0; + } + +auth_ok: + if (server_xtn->cfg[CFG_DOCROOT].ptr || qpath[0] != QSE_MT('/')) { const qse_mchar_t* ta[4]; qse_size_t idx = 0; - if (server_xtn->docroot.ptr) ta[idx++] = server_xtn->docroot.ptr; + if (server_xtn->cfg[CFG_DOCROOT].ptr) ta[idx++] = server_xtn->cfg[CFG_DOCROOT].ptr; if (qpath[0] != QSE_MT('/')) ta[idx++] = QSE_MT("/"); ta[idx++] = qpath; ta[idx++] = QSE_NULL; @@ -1912,10 +1901,11 @@ return 0; if (xpath != qpath) QSE_MMGR_FREE (httpd->mmgr, xpath); - if (server_xtn->docroot.ptr) + if (server_xtn->cfg[CFG_DOCROOT].ptr) { xpath = qse_mbsxdup2 ( - server_xtn->docroot.ptr, server_xtn->docroot.len, + server_xtn->cfg[CFG_DOCROOT].ptr, + server_xtn->cfg[CFG_DOCROOT].len, qpath, ext - qpath + extinfo[i].len, httpd->mmgr); } else @@ -1935,7 +1925,7 @@ return 0; return -1; } - docroot = server_xtn->docroot.ptr; + docroot = server_xtn->cfg[CFG_DOCROOT].ptr; } else { @@ -1992,5 +1982,7 @@ int qse_httpd_loopstd (qse_httpd_t* httpd, qse_httpd_cbstd_t* cbstd, qse_ntime_t if (cbstd) xtn->cbstd = cbstd; else xtn->cbstd = &httpd_cbstd; - return qse_httpd_loop (httpd, &httpd_system_callbacks, &httpd_request_callbacks, timeout); + return qse_httpd_loop ( + httpd, &httpd_system_callbacks, + &httpd_request_callbacks, timeout); } diff --git a/qse/lib/net/httpd.c b/qse/lib/net/httpd.c index 88d89a77..61199c04 100644 --- a/qse/lib/net/httpd.c +++ b/qse/lib/net/httpd.c @@ -57,6 +57,7 @@ qse_httpd_t* qse_httpd_open (qse_mmgr_t* mmgr, qse_size_t xtnsize) return QSE_NULL; } + QSE_MEMSET (httpd + 1, 0, xtnsize); return httpd; } @@ -82,7 +83,6 @@ int qse_httpd_init (qse_httpd_t* httpd, qse_mmgr_t* mmgr) void qse_httpd_fini (qse_httpd_t* httpd) { -/* TODO */ free_server_list (httpd); } diff --git a/qse/samples/cmn/Makefile.am b/qse/samples/cmn/Makefile.am index dc461a5b..48a41475 100644 --- a/qse/samples/cmn/Makefile.am +++ b/qse/samples/cmn/Makefile.am @@ -39,6 +39,7 @@ bin_PROGRAMS = \ str01 \ time \ tre01 \ + uri01 \ xma LDFLAGS = -L../../lib/cmn diff --git a/qse/samples/cmn/Makefile.in b/qse/samples/cmn/Makefile.in index fbca9ae7..5e8d3873 100644 --- a/qse/samples/cmn/Makefile.in +++ b/qse/samples/cmn/Makefile.in @@ -42,7 +42,7 @@ bin_PROGRAMS = chr01$(EXEEXT) env$(EXEEXT) dll$(EXEEXT) fio01$(EXEEXT) \ pio$(EXEEXT) pma$(EXEEXT) rex01$(EXEEXT) rbt$(EXEEXT) \ sio01$(EXEEXT) sio02$(EXEEXT) sio03$(EXEEXT) sll$(EXEEXT) \ slmb01$(EXEEXT) str01$(EXEEXT) time$(EXEEXT) tre01$(EXEEXT) \ - xma$(EXEEXT) + uri01$(EXEEXT) xma$(EXEEXT) @WCHAR_TRUE@@WIN32_TRUE@am__append_1 = $(UNICOWS_LIBS) subdir = samples/cmn DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in @@ -190,6 +190,10 @@ am_tre01_OBJECTS = tre01.$(OBJEXT) tre01_OBJECTS = $(am_tre01_OBJECTS) tre01_LDADD = $(LDADD) tre01_DEPENDENCIES = $(am__DEPENDENCIES_2) +uri01_SOURCES = uri01.c +uri01_OBJECTS = uri01.$(OBJEXT) +uri01_LDADD = $(LDADD) +uri01_DEPENDENCIES = $(am__DEPENDENCIES_2) am_xma_OBJECTS = xma.$(OBJEXT) xma_OBJECTS = $(am_xma_OBJECTS) xma_LDADD = $(LDADD) @@ -217,7 +221,7 @@ SOURCES = $(chr01_SOURCES) $(dll_SOURCES) $(env_SOURCES) \ $(rbt_SOURCES) $(rex01_SOURCES) $(sio01_SOURCES) \ $(sio02_SOURCES) $(sio03_SOURCES) $(sll_SOURCES) \ $(slmb01_SOURCES) $(str01_SOURCES) $(time_SOURCES) \ - $(tre01_SOURCES) $(xma_SOURCES) + $(tre01_SOURCES) uri01.c $(xma_SOURCES) DIST_SOURCES = $(chr01_SOURCES) $(dll_SOURCES) $(env_SOURCES) \ $(fio01_SOURCES) $(fio02_SOURCES) $(fma_SOURCES) \ $(fmt01_SOURCES) $(fmt02_SOURCES) $(fs01_SOURCES) \ @@ -228,7 +232,7 @@ DIST_SOURCES = $(chr01_SOURCES) $(dll_SOURCES) $(env_SOURCES) \ $(rbt_SOURCES) $(rex01_SOURCES) $(sio01_SOURCES) \ $(sio02_SOURCES) $(sio03_SOURCES) $(sll_SOURCES) \ $(slmb01_SOURCES) $(str01_SOURCES) $(time_SOURCES) \ - $(tre01_SOURCES) $(xma_SOURCES) + $(tre01_SOURCES) uri01.c $(xma_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -598,6 +602,9 @@ time$(EXEEXT): $(time_OBJECTS) $(time_DEPENDENCIES) $(EXTRA_time_DEPENDENCIES) tre01$(EXEEXT): $(tre01_OBJECTS) $(tre01_DEPENDENCIES) $(EXTRA_tre01_DEPENDENCIES) @rm -f tre01$(EXEEXT) $(LINK) $(tre01_OBJECTS) $(tre01_LDADD) $(LIBS) +uri01$(EXEEXT): $(uri01_OBJECTS) $(uri01_DEPENDENCIES) $(EXTRA_uri01_DEPENDENCIES) + @rm -f uri01$(EXEEXT) + $(LINK) $(uri01_OBJECTS) $(uri01_LDADD) $(LIBS) xma$(EXEEXT): $(xma_OBJECTS) $(xma_DEPENDENCIES) $(EXTRA_xma_DEPENDENCIES) @rm -f xma$(EXEEXT) $(LINK) $(xma_OBJECTS) $(xma_LDADD) $(LIBS) @@ -640,6 +647,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str01.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tre01.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uri01.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xma.Po@am__quote@ .c.o: diff --git a/qse/samples/cmn/uri01.c b/qse/samples/cmn/uri01.c new file mode 100644 index 00000000..42943739 --- /dev/null +++ b/qse/samples/cmn/uri01.c @@ -0,0 +1,139 @@ +#include +#include +#include +#include + +#include +#if defined(_WIN32) +# include +#endif + +static void xxx (const qse_wchar_t* ptr, qse_size_t len) +{ + if (ptr) + { + qse_size_t i; + qse_printf (QSE_T(" [")); + for (i = 0; i < len; i++) + qse_printf (QSE_T("%hc"), ptr[i]); + qse_printf (QSE_T("] ")); + } + else + { + qse_printf (QSE_T(" (null) ")); + } +} + +static int test_main (int argc, qse_char_t* argv[], qse_char_t* envp[]) +{ + static const qse_wchar_t* wcs[] = + { + QSE_WT("http://www.google.com"), + QSE_WT("http://www.google.com:80"), + QSE_WT("http://abc@www.google.com:80"), + QSE_WT("http://abc:def@www.google.com:80"), + QSE_WT("http://abc:def@www.google.com:80/"), + QSE_WT("http://abc:def@www.google.com:80/?#"), + QSE_WT("http://abc:def@www.google.com:80/abcdef/ghi?kkk=23#fragment"), + QSE_WT("http://abc:def@www.google.com:80/abcdef/ghi#fragment#fragment"), + QSE_WT("http://abc:def@www@.google.com:80/abcdef/ghi#fragment#fragment"), + QSE_WT("http://@@@@@abc:def@www@.google.com:80/abcdef/ghi#fragment#fragment") + }; + + qse_size_t i; + qse_uri_t uri; + + for (i = 0; i < QSE_COUNTOF(wcs); i++) + { + qse_printf (QSE_T("[%ls] => "), wcs[i]); + if (qse_wcstouri (wcs[i], &uri, 0) <= -1) + { + qse_printf (QSE_T("[ERROR]")); + } + else + { + xxx (uri.scheme.ptr, uri.scheme.len); + xxx (uri.auth.user.ptr, uri.auth.user.len); + xxx (uri.auth.pass.ptr, uri.auth.pass.len); + xxx (uri.host.ptr, uri.host.len); + xxx (uri.port.ptr, uri.port.len); + xxx (uri.path.ptr, uri.path.len); + xxx (uri.query.ptr, uri.query.len); + xxx (uri.frag.ptr, uri.frag.len); + } + qse_printf (QSE_T("\n")); + } + + qse_printf (QSE_T("================================================\n")); + + for (i = 0; i < QSE_COUNTOF(wcs); i++) + { + qse_printf (QSE_T("[%ls] => "), wcs[i]); + if (qse_wcstouri (wcs[i], &uri, QSE_WCSTOURI_NOQUERY | QSE_WCSTOURI_NOAUTH) <= -1) + { + qse_printf (QSE_T("[ERROR]")); + } + else + { + xxx (uri.scheme.ptr, uri.scheme.len); + xxx (uri.auth.user.ptr, uri.auth.user.len); + xxx (uri.auth.pass.ptr, uri.auth.pass.len); + xxx (uri.host.ptr, uri.host.len); + xxx (uri.port.ptr, uri.port.len); + xxx (uri.path.ptr, uri.path.len); + xxx (uri.query.ptr, uri.query.len); + xxx (uri.frag.ptr, uri.frag.len); + } + qse_printf (QSE_T("\n")); + } + + qse_printf (QSE_T("================================================\n")); + + for (i = 0; i < QSE_COUNTOF(wcs); i++) + { + qse_printf (QSE_T("[%ls] => "), wcs[i]); + if (qse_wcstouri (wcs[i], &uri, QSE_WCSTOURI_NOQUERY | QSE_WCSTOURI_NOAUTH | QSE_WCSTOURI_NOFRAG) <= -1) + { + qse_printf (QSE_T("[ERROR]")); + } + else + { + xxx (uri.scheme.ptr, uri.scheme.len); + xxx (uri.auth.user.ptr, uri.auth.user.len); + xxx (uri.auth.pass.ptr, uri.auth.pass.len); + xxx (uri.host.ptr, uri.host.len); + xxx (uri.port.ptr, uri.port.len); + xxx (uri.path.ptr, uri.path.len); + xxx (uri.query.ptr, uri.query.len); + xxx (uri.frag.ptr, uri.frag.len); + } + qse_printf (QSE_T("\n")); + } + + qse_printf (QSE_T("================================================\n")); + return 0; +} + +int qse_main (int argc, qse_achar_t* argv[], qse_achar_t* envp[]) +{ +#if defined(_WIN32) + char locale[100]; + UINT codepage = GetConsoleOutputCP(); + if (codepage == CP_UTF8) + { + /*SetConsoleOUtputCP (CP_UTF8);*/ + qse_setdflcmgr (qse_utf8cmgr); + } + else + { + sprintf (locale, ".%u", (unsigned int)codepage); + setlocale (LC_ALL, locale); + qse_setdflcmgrbyid (QSE_CMGR_SLMB); + } +#else + setlocale (LC_ALL, ""); + qse_setdflcmgrbyid (QSE_CMGR_SLMB); +#endif + return qse_runmainwithenv (argc, argv, envp, test_main); +} + diff --git a/qse/samples/net/httpd02.c b/qse/samples/net/httpd02.c index f59ac071..1c7e8f2c 100644 --- a/qse/samples/net/httpd02.c +++ b/qse/samples/net/httpd02.c @@ -55,6 +55,7 @@ static void sigint (int sig) } /* --------------------------------------------------------------------- */ +#if 0 static qse_httpd_server_t* attach_server (qse_httpd_t* httpd, const qse_char_t* uri) { qse_httpd_server_t server, * xserver; @@ -93,6 +94,7 @@ static qse_httpd_server_t* attach_server (qse_httpd_t* httpd, const qse_char_t* return xserver; } +#endif /* --------------------------------------------------------------------- */ static int httpd_main (int argc, qse_char_t* argv[]) @@ -116,7 +118,7 @@ static int httpd_main (int argc, qse_char_t* argv[]) for (i = 1; i < argc; i++) { - if (attach_server (httpd, argv[i]) == QSE_NULL) + if (qse_httpd_attachserverstd (httpd, argv[i], 0) == QSE_NULL) { qse_fprintf (QSE_STDERR, QSE_T("Failed to add httpd listener - %s\n"), argv[i]);