├── src ├── main.c ├── http_accesslog.c ├── Makefile.in ├── syscall.c ├── mime.c ├── version.c ├── http_auth.c ├── http_header.c ├── stream.c ├── util.c ├── hook.c ├── config.c ├── http_main.c ├── http_status.c └── child.c ├── lib ├── qlibc │ ├── examples │ │ ├── config.def │ │ ├── config.conf │ │ ├── config.c │ │ ├── vector.c │ │ ├── vector_obj.c │ │ ├── Makefile.in │ │ ├── queue.c │ │ ├── stack.c │ │ ├── hasharr.c │ │ ├── hashtbl.c │ │ ├── list.c │ │ └── listtbl.c │ ├── src │ │ ├── internal │ │ │ ├── doxygen_tailer.html │ │ │ ├── doxygen_header.html │ │ │ ├── md5 │ │ │ │ └── md5.h │ │ │ ├── qinternal.c │ │ │ └── doxygen_layout.xml │ │ ├── astyle.conf │ │ ├── utilities │ │ │ ├── qlibc.c │ │ │ ├── qsystem.c │ │ │ ├── qcount.c │ │ │ ├── qsocket.c │ │ │ └── qtime.c │ │ ├── Makefile.in │ │ └── ipc │ │ │ ├── qshm.c │ │ │ └── qsem.c │ ├── README │ ├── COPYING │ ├── config.h.in │ ├── Makefile.in │ └── configure.ac ├── update_qlibc.sh └── Makefile.in ├── htdocs └── index.html ├── conf ├── mimetypes.conf ├── qhttpd.conf.dist └── qhttpd.lua.dist ├── COPYING ├── config.h.in ├── README.md ├── Makefile.in └── configure.ac /src/main.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolkykim/qhttpd/HEAD/src/main.c -------------------------------------------------------------------------------- /lib/qlibc/examples/config.def: -------------------------------------------------------------------------------- 1 | # This is "config.def" file. 2 | prefix = /usr/local 3 | bin = ${prefix}/bin 4 | log = ${prefix}/log 5 | user = unknown 6 | host = unknown 7 | -------------------------------------------------------------------------------- /lib/qlibc/src/internal/doxygen_tailer.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /htdocs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | qHttpd 4 | 5 | 6 |
7 |

Welcome to qHttpd

8 |

qHttpd Project

9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /lib/qlibc/src/astyle.conf: -------------------------------------------------------------------------------- 1 | # 2 | # qlibc coding convention 3 | # 4 | --verbose 5 | --style=kr 6 | --indent=spaces=4 7 | --indent-switches 8 | --indent-preprocessor 9 | --min-conditional-indent=0 10 | --pad-header 11 | --convert-tabs 12 | --align-pointer=name 13 | --lineend=linux 14 | -------------------------------------------------------------------------------- /lib/qlibc/README: -------------------------------------------------------------------------------- 1 | DOCUMENTS AND WEBSITE 2 | ===================== 3 | 4 | All documents are available throught the project website at: 5 | 6 | http://www.qdecoder.org 7 | 8 | CONTRIBUTORS AND CONTACTS 9 | ========================= 10 | Seungyoung Kim - Author 11 | -------------------------------------------------------------------------------- /lib/qlibc/examples/config.conf: -------------------------------------------------------------------------------- 1 | # This is "config.conf" file. 2 | # A line which starts with # character is comment 3 | 4 | @INCLUDE config.def 5 | 6 | # this is global section 7 | prefix=/tmp 8 | log=${prefix}/log 9 | user=${%USER} 10 | host=${!/bin/hostname -s} 11 | id=${user}@${host} 12 | 13 | # now entering into 'system' section 14 | [system] 15 | ostype=${%OSTYPE} 16 | machtype=${%MACHTYPE} 17 | 18 | # entering into 'daemon' section 19 | [daemon] 20 | port=1234 21 | name=${user}_${host}_${system.ostype}_${system.machtype} 22 | 23 | # go back to root 24 | [] 25 | rev=822 26 | -------------------------------------------------------------------------------- /conf/mimetypes.conf: -------------------------------------------------------------------------------- 1 | ## 2 | ## qHttpd Mime Configuration 3 | ## 4 | ## $Id: mimetypes.conf 218 2012-05-16 09:56:20Z seungyoung.kim $ 5 | _DEF_ = application/octet-stream 6 | AVI = video/x-msvideo 7 | BMP = image/bmp 8 | BZ2 - application/x-bzip2 9 | CSS = text/css 10 | EXE = application/octet-stream 11 | FLV = flv-application/octet-stream 12 | GIF = image/gif 13 | GZ = application/x-gzip 14 | HTM = text/html 15 | HTML = text/html 16 | JPEG = image/jpeg 17 | JPG = image/jpeg 18 | MP3 = audio/mpeg 19 | MPG = video/mpeg 20 | PDF = application/pdf 21 | PNG = image/png 22 | SVG = image/svg+xml 23 | TAR = application/x-tar 24 | TGZ = application/x-gzip 25 | TXT = text/plain 26 | WMA = audio/x-ms-wma 27 | WMV = video/x-ms-wmv 28 | ZIP = application/x-zip-compressed 29 | -------------------------------------------------------------------------------- /lib/qlibc/src/internal/doxygen_header.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | $title 14 | 15 | 16 | 17 | 18 | 19 |

qLibc API Reference

20 | -------------------------------------------------------------------------------- /lib/update_qlibc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | OLDQLIBC="./qlibc" 4 | NEWQLIBC="./qlibc_new" 5 | PATCH="qlibc.patch" 6 | 7 | ## Clean old 8 | if [ -f $OLDQLIBC/Makefile ]; then 9 | (cd $OLDQLIBC/src; make cleandoc) 10 | (cd $OLDQLIBC; make distclean) 11 | fi 12 | 13 | # Get new 14 | if [ -d $NEWQLIBC ]; then 15 | rm -rf $NEWQLIBC 16 | fi 17 | 18 | echo "Retrieving files from SVN repo..." 19 | svn export https://svn.qdecoder.org/qlibc/trunk $NEWQLIBC > /dev/null 20 | 21 | # Diff 22 | DIFF=`diff -r $OLDQLIBC $NEWQLIBC` 23 | if [ ! "$DIFF" = "" ]; then 24 | #diff -rupN $OLDQLIBC $NEWQLIBC > $PATCH 25 | diff -rup $OLDQLIBC $NEWQLIBC > $PATCH 26 | echo "--[DIFF]---------------------------------------------------------" 27 | cat $PATCH 28 | echo "-----------------------------------------------------------------" 29 | echo "Patching files..." 30 | patch -p0 --posix < $PATCH 31 | 32 | ## Check again 33 | VERIFY=`diff -r $OLDQLIBC $NEWQLIBC` 34 | if [ ! "$VERIFY" = "" ]; then 35 | echo "--[VERIFY]-------------------------------------------------------" 36 | echo "$VERIFY" 37 | echo "-----------------------------------------------------------------" 38 | echo "Update completed but there are something need to be handled." 39 | else 40 | echo "Update completed." 41 | fi 42 | else 43 | echo "Completed - No changes." 44 | fi 45 | 46 | # Clean up 47 | #if [ -d $NEWQLIBC ]; then 48 | # rm -r $NEWQLIBC 49 | #fi 50 | 51 | #if [ -f $PATCH ]; then 52 | # rm $PATCH 53 | #fi 54 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | qHttpd License 2 | ============== 3 | 4 | ============================================================================== 5 | qHttpd - http://www.qdecoder.org 6 | 7 | Copyright (c) 2008-2012 Seungyoung Kim. 8 | All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright notice, 14 | this list of conditions and the following disclaimer. 15 | 2. Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | ============================================================================== 31 | (end of COPYRIGHT) 32 | -------------------------------------------------------------------------------- /lib/qlibc/COPYING: -------------------------------------------------------------------------------- 1 | qLibc License 2 | ============= 3 | 4 | ============================================================================== 5 | qLibc - http://www.qdecoder.org 6 | 7 | Copyright (c) 2010-2012 Seungyoung Kim. 8 | All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright notice, 14 | this list of conditions and the following disclaimer. 15 | 2. Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | ============================================================================== 31 | (end of COPYRIGHT) 32 | 33 | -------------------------------------------------------------------------------- /lib/qlibc/src/internal/md5/md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 3 | * rights reserved. 4 | * 5 | * License to copy and use this software is granted provided that it 6 | * is identified as the "RSA Data Security, Inc. MD5 Message-Digest 7 | * Algorithm" in all material mentioning or referencing this software 8 | * or this function. 9 | * 10 | * License is also granted to make and use derivative works provided 11 | * that such works are identified as "derived from the RSA Data 12 | * Security, Inc. MD5 Message-Digest Algorithm" in all material 13 | * mentioning or referencing the derived work. 14 | * 15 | * RSA Data Security, Inc. makes no representations concerning either 16 | * the merchantability of this software or the suitability of this 17 | * software for any particular purpose. It is provided "as is" 18 | * without express or implied warranty of any kind. 19 | * 20 | * These notices must be retained in any copies of any part of this 21 | * documentation and/or software. 22 | */ 23 | 24 | #ifndef _Q_MD5_H_ 25 | #define _Q_MD5_H_ 26 | 27 | #define MD5_BLOCK_LENGTH 64 28 | #define MD5_DIGEST_LENGTH 16 29 | #define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1) 30 | 31 | /* MD5 context. */ 32 | typedef struct MD5Context { 33 | u_int32_t state[4]; /* state (ABCD) */ 34 | u_int32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ 35 | unsigned char buffer[64]; /* input buffer */ 36 | } MD5_CTX; 37 | 38 | #include 39 | 40 | __BEGIN_DECLS 41 | void MD5Init (MD5_CTX *); 42 | void MD5Update (MD5_CTX *, const unsigned char *, unsigned int); 43 | void MD5Final (unsigned char [16], MD5_CTX *); 44 | char * MD5End(MD5_CTX *, char *); 45 | char * MD5File(const char *, char *); 46 | char * MD5FileChunk(const char *, char *, off_t, off_t); 47 | char * MD5Data(const unsigned char *, unsigned int, char *); 48 | __END_DECLS 49 | 50 | #endif /* _Q_MD5_H_ */ 51 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Define to 1 if you have the header file, and it defines `DIR'. 4 | */ 5 | #undef HAVE_DIRENT_H 6 | 7 | /* Define to 1 if you have the header file. */ 8 | #undef HAVE_INTTYPES_H 9 | 10 | /* Define to 1 if you have the header file. */ 11 | #undef HAVE_MEMORY_H 12 | 13 | /* Define to 1 if you have the header file, and it defines `DIR'. */ 14 | #undef HAVE_NDIR_H 15 | 16 | /* Define to 1 if stdbool.h conforms to C99. */ 17 | #undef HAVE_STDBOOL_H 18 | 19 | /* Define to 1 if you have the header file. */ 20 | #undef HAVE_STDINT_H 21 | 22 | /* Define to 1 if you have the header file. */ 23 | #undef HAVE_STDLIB_H 24 | 25 | /* Define to 1 if you have the header file. */ 26 | #undef HAVE_STRINGS_H 27 | 28 | /* Define to 1 if you have the header file. */ 29 | #undef HAVE_STRING_H 30 | 31 | /* Define to 1 if you have the header file, and it defines `DIR'. 32 | */ 33 | #undef HAVE_SYS_DIR_H 34 | 35 | /* Define to 1 if you have the header file, and it defines `DIR'. 36 | */ 37 | #undef HAVE_SYS_NDIR_H 38 | 39 | /* Define to 1 if you have the header file. */ 40 | #undef HAVE_SYS_STAT_H 41 | 42 | /* Define to 1 if you have the header file. */ 43 | #undef HAVE_SYS_TYPES_H 44 | 45 | /* Define to 1 if you have the header file. */ 46 | #undef HAVE_UNISTD_H 47 | 48 | /* Define to 1 if the system has the type `_Bool'. */ 49 | #undef HAVE__BOOL 50 | 51 | /* Define to the address where bug reports for this package should be sent. */ 52 | #undef PACKAGE_BUGREPORT 53 | 54 | /* Define to the full name of this package. */ 55 | #undef PACKAGE_NAME 56 | 57 | /* Define to the full name and version of this package. */ 58 | #undef PACKAGE_STRING 59 | 60 | /* Define to the one symbol short name of this package. */ 61 | #undef PACKAGE_TARNAME 62 | 63 | /* Define to the version of this package. */ 64 | #undef PACKAGE_VERSION 65 | 66 | /* Define to 1 if you have the ANSI C header files. */ 67 | #undef STDC_HEADERS 68 | 69 | /* Define to `long' if does not define. */ 70 | #undef off_t 71 | 72 | /* Define to `unsigned' if does not define. */ 73 | #undef size_t 74 | -------------------------------------------------------------------------------- /lib/Makefile.in: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## qHttpd - http://www.qdecoder.org 3 | ## 4 | ## Copyright (c) 2008-2012 Seungyoung Kim. 5 | ## All rights reserved. 6 | ## 7 | ## Redistribution and use in source and binary forms, with or without 8 | ## modification, are permitted provided that the following conditions are met: 9 | ## 10 | ## 1. Redistributions of source code must retain the above copyright notice, 11 | ## this list of conditions and the following disclaimer. 12 | ## 2. Redistributions in binary form must reproduce the above copyright notice, 13 | ## this list of conditions and the following disclaimer in the documentation 14 | ## and/or other materials provided with the distribution. 15 | ## 16 | ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | ## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | ## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ## ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | ## LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | ## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | ## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | ## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | ## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | ## POSSIBILITY OF SUCH DAMAGE. 27 | ################################################################################ 28 | ## $Id$ 29 | ################################################################################ 30 | 31 | all: all-qlibc 32 | 33 | all-qlibc: 34 | @if [ ! -f "qlibc/Makefile" ]; then \ 35 | (cd qlibc; ./configure); \ 36 | fi 37 | @if [ ! -f "qlibc/src/libqlibc.a" ]; then \ 38 | (cd qlibc; make clean all); \ 39 | fi 40 | 41 | clean: clean-qlibc 42 | 43 | clean-qlibc: 44 | @if [ -f "qlibc/Makefile" ]; then \ 45 | (cd qlibc; make clean); \ 46 | fi 47 | 48 | distclean: distclean-qlibc 49 | 50 | distclean-qlibc: 51 | @if [ -f "qlibc/Makefile" ] ; then \ 52 | (cd qlibc; make distclean); \ 53 | fi 54 | rm -f Makefile 55 | rm -f qlibc.patch 56 | rm -rf qlibc_new 57 | 58 | -------------------------------------------------------------------------------- /lib/qlibc/examples/config.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qLibc - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2010-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: config.c 77 2012-04-11 01:19:11Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include "qlibc.h" 32 | #include "qlibcext.h" 33 | 34 | #define CONF_PATH "config.conf" 35 | 36 | int main(void) 37 | { 38 | #ifdef DISABLE_QCONFIG 39 | printf("qconfig extension is disabled.\n" 40 | "Compile qLibc without '--disable-qconfig' option.\n"); 41 | return 1; 42 | #else 43 | qlisttbl_t *tbl = qconfig_parse_file(NULL, CONF_PATH, '=', true); 44 | if (tbl == NULL) { 45 | printf("Failed to open '" CONF_PATH "'.\n"); 46 | return -1; 47 | } 48 | tbl->debug(tbl, stdout); 49 | 50 | return 0; 51 | #endif 52 | } 53 | -------------------------------------------------------------------------------- /lib/qlibc/config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Define to 1 if you have the header file, and it defines `DIR'. 4 | */ 5 | #undef HAVE_DIRENT_H 6 | 7 | /* Define to 1 if you have the header file. */ 8 | #undef HAVE_INTTYPES_H 9 | 10 | /* Define to 1 if you have the `pthread' library (-lpthread). */ 11 | #undef HAVE_LIBPTHREAD 12 | 13 | /* Define to 1 if you have the header file. */ 14 | #undef HAVE_MEMORY_H 15 | 16 | /* Define to 1 if you have the header file, and it defines `DIR'. */ 17 | #undef HAVE_NDIR_H 18 | 19 | /* Define to 1 if stdbool.h conforms to C99. */ 20 | #undef HAVE_STDBOOL_H 21 | 22 | /* Define to 1 if you have the header file. */ 23 | #undef HAVE_STDINT_H 24 | 25 | /* Define to 1 if you have the header file. */ 26 | #undef HAVE_STDLIB_H 27 | 28 | /* Define to 1 if you have the header file. */ 29 | #undef HAVE_STRINGS_H 30 | 31 | /* Define to 1 if you have the header file. */ 32 | #undef HAVE_STRING_H 33 | 34 | /* Define to 1 if you have the header file, and it defines `DIR'. 35 | */ 36 | #undef HAVE_SYS_DIR_H 37 | 38 | /* Define to 1 if you have the header file, and it defines `DIR'. 39 | */ 40 | #undef HAVE_SYS_NDIR_H 41 | 42 | /* Define to 1 if you have the header file. */ 43 | #undef HAVE_SYS_STAT_H 44 | 45 | /* Define to 1 if you have the header file. */ 46 | #undef HAVE_SYS_TYPES_H 47 | 48 | /* Define to 1 if you have the header file. */ 49 | #undef HAVE_UNISTD_H 50 | 51 | /* Define to 1 if the system has the type `_Bool'. */ 52 | #undef HAVE__BOOL 53 | 54 | /* Define to the address where bug reports for this package should be sent. */ 55 | #undef PACKAGE_BUGREPORT 56 | 57 | /* Define to the full name of this package. */ 58 | #undef PACKAGE_NAME 59 | 60 | /* Define to the full name and version of this package. */ 61 | #undef PACKAGE_STRING 62 | 63 | /* Define to the one symbol short name of this package. */ 64 | #undef PACKAGE_TARNAME 65 | 66 | /* Define to the version of this package. */ 67 | #undef PACKAGE_VERSION 68 | 69 | /* Define to 1 if you have the ANSI C header files. */ 70 | #undef STDC_HEADERS 71 | 72 | /* Define to `long' if does not define. */ 73 | #undef off_t 74 | 75 | /* Define to `unsigned' if does not define. */ 76 | #undef size_t 77 | -------------------------------------------------------------------------------- /lib/qlibc/src/utilities/qlibc.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qLibc - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2010-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: qlibc.c 59 2012-04-04 23:53:38Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | /** 32 | * @file qlibc.c qLibc version APIs. 33 | */ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include "qlibc.h" 40 | #include "qinternal.h" 41 | 42 | /** 43 | * Get the version string of qLibc library 44 | * 45 | * @return a pointer of version string 46 | */ 47 | const char *qlibc_version(void) 48 | { 49 | return _Q_VERSION; 50 | } 51 | 52 | /** 53 | * Returns this library is compiled with thread-safe option. --enable-threadsafe 54 | * 55 | * @return true if it's thread-safe, otherwise returns false. 56 | */ 57 | bool qlibc_is_threadsafe(void) 58 | { 59 | #ifdef ENABLE_THREADSAFE 60 | return true; 61 | #else 62 | return false; 63 | #endif 64 | } 65 | 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | qHttpd 2 | ====== 3 | 4 | ## What's qHttpd? 5 | 6 | The goal of qHttpd Project is building a highly customizable HTTP server which can be used in many projects not only as a HTTP contents delivery purpose but also an internal protocol purpose. 7 | 8 | Are you looking for customizable HTTP server for your own software development needs? Are you considering to develop a protocol like a HTTP protocol to use as a inter-communication protol for your software? Do you want to modify standard HTTP protocol and add your own methods to fit in your needs? 9 | If your answer is YES to one of these questions, qHttpd is just for you. Take a look. It's simple, fast and compact! 10 | 11 | ## Features 12 | 13 | * Supports **HTTP/1.1**, HTTP/1.0, HTTP/0.9 14 | * Supports completely working codebase for standard HTTP methods: OPTIONS, HEAD, GET, PUT(supports chunked transfer-encoding) 15 | * Also supports **WebDAV extension**: PROPFIND, PROPPATCH, MKCOL, MOVE, DELETE, LOCK, UNLOCK 16 | * Includes **C hooking**/customizing samples codes. 17 | * Supports external **LUA script hooking**. 18 | * Supports HTTP Basic Auth Module (refer http_auth.c) 19 | * Supports Virtual Host (refer hook.c) 20 | * You can **easily customize/add methods**. 21 | * Supports server statistics page. 22 | * Supports mime types. 23 | * Supports rotating file log. 24 | 25 | ## How easy adding a new method? 26 | 27 | ### Example) Adding a new method in C 28 | 29 | ```C 30 | int hookRequestHandler(struct HttpRequest *pReq, struct HttpResponse *pRes) { 31 | int nResCode = 0; 32 | 33 | // method hooking 34 | if(!strcmp(pReq->pszRequestMethod, "MY_METHOD")) { 35 | nResCode = my_method(pReq, pRes); 36 | } 37 | return nResCode; 38 | } 39 | 40 | int my_method(struct HttpRequest *pReq, struct HttpResponse *pRes) { 41 | const char *txt = "Nice to meet you~" 42 | 43 | httpResponseSetCode(pRes, HTTP_CODE_OK, true); 44 | httpHeaderSetStr(pRes->pHeaders, "MY_HEADER", "Hi~"); 45 | httpResponseSetContent(pRes, "httpd/plain", txt, strlen(txt)); 46 | } 47 | ``` 48 | 49 | ### Example) Modifying response using LUA script 50 | ```LUA 51 | function responseHandler() 52 | local code = response:getCode(); 53 | 54 | out = assert(io.open("/tmp/test.log", "a+")); 55 | out:write("Response Code = ",code,"\n"); 56 | out:write("\n"); 57 | out:close(); 58 | 59 | if (code == 200) then 60 | response:setHeader("Server", "milk/1.0.0"); 61 | end 62 | return 0; 63 | end 64 | ``` 65 | 66 | -------------------------------------------------------------------------------- /lib/qlibc/Makefile.in: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## qLibc - http://www.qdecoder.org 3 | ## 4 | ## Copyright (c) 2010-2012 Seungyoung Kim. 5 | ## All rights reserved. 6 | ## 7 | ## Redistribution and use in source and binary forms, with or without 8 | ## modification, are permitted provided that the following conditions are met: 9 | ## 10 | ## 1. Redistributions of source code must retain the above copyright notice, 11 | ## this list of conditions and the following disclaimer. 12 | ## 2. Redistributions in binary form must reproduce the above copyright notice, 13 | ## this list of conditions and the following disclaimer in the documentation 14 | ## and/or other materials provided with the distribution. 15 | ## 16 | ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | ## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | ## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ## ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | ## LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | ## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | ## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | ## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | ## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | ## POSSIBILITY OF SUCH DAMAGE. 27 | ################################################################################ 28 | ## $Id: Makefile.in 67 2012-04-06 00:29:22Z seungyoung.kim $ 29 | ################################################################################ 30 | 31 | RM = @RM@ 32 | 33 | all: 34 | @for DIR in src; do \ 35 | echo "===> $${DIR}"; \ 36 | (cd $${DIR}; make all); \ 37 | echo "<=== $${DIR}"; \ 38 | done 39 | 40 | install: 41 | (cd src/; make install) 42 | 43 | deinstall: uninstall 44 | uninstall: 45 | (cd src/; make deinstall) 46 | 47 | clean: 48 | @for DIR in src; do \ 49 | echo "===> $${DIR}"; \ 50 | (cd $${DIR}; make clean); \ 51 | echo "<=== $${DIR}"; \ 52 | done 53 | 54 | distclean: clean 55 | @for DIR in src examples; do \ 56 | echo "===> $${DIR}"; \ 57 | (cd $${DIR}; make clean; ${RM} -f Makefile); \ 58 | echo "<=== $${DIR}"; \ 59 | done 60 | ${RM} -rf autom4te.cache 61 | ${RM} -f configure.lineno config.log config.status config.h 62 | ${RM} -f Makefile 63 | 64 | -------------------------------------------------------------------------------- /lib/qlibc/examples/vector.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qLibc - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2010-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: vector.c 78 2012-04-11 03:52:25Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "qlibc.h" 37 | 38 | int main(void) 39 | { 40 | qvector_t *vector = qvector(); 41 | 42 | // add elements 43 | vector->addstr(vector, "AB"); // no need to supply size 44 | vector->addstrf(vector, "%d", 12); // for formatted string 45 | vector->addstr(vector, "CD"); 46 | 47 | char *final = vector->tostring(vector); 48 | // get the chunk as a string 49 | 50 | // print out 51 | vector->debug(vector, stdout); 52 | printf("Number of elements = %zu\n", vector->size(vector)); 53 | printf("Final string = %s\n", final); 54 | 55 | // release 56 | free(final); 57 | vector->free(vector); 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /src/http_accesslog.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qHttpd - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2008-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: http_accesslog.c 214 2012-05-05 00:33:31Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include "qhttpd.h" 32 | 33 | bool httpAccessLog(struct HttpRequest *pReq, struct HttpResponse *pRes) 34 | { 35 | if (pReq->pszRequestMethod == NULL) return false; 36 | 37 | const char *pszHost = httpHeaderGetStr(pReq->pHeaders, "HOST"); 38 | const char *pszReferer = httpHeaderGetStr(pReq->pHeaders, "REFERER"); 39 | const char *pszAgent = httpHeaderGetStr(pReq->pHeaders, "USER-AGENT"); 40 | 41 | g_acclog->writef(g_acclog, "%s - - [%s] \"%s http://%s%s %s\" %d %jd \"%s\" \"%s\"", 42 | poolGetConnAddr(), qtime_gmt_staticstr(poolGetConnReqTime()), 43 | pReq->pszRequestMethod, pszHost, pReq->pszRequestUri, pReq->pszHttpVersion, 44 | pRes->nResponseCode, pRes->nContentsLength, 45 | (pszReferer != NULL) ? pszReferer : "-", 46 | (pszAgent != NULL) ? pszAgent : "-" 47 | ); 48 | 49 | return true; 50 | } 51 | -------------------------------------------------------------------------------- /src/Makefile.in: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## qHttpd - http://www.qdecoder.org 3 | ## 4 | ## Copyright (c) 2008-2012 Seungyoung Kim. 5 | ## All rights reserved. 6 | ## 7 | ## Redistribution and use in source and binary forms, with or without 8 | ## modification, are permitted provided that the following conditions are met: 9 | ## 10 | ## 1. Redistributions of source code must retain the above copyright notice, 11 | ## this list of conditions and the following disclaimer. 12 | ## 2. Redistributions in binary form must reproduce the above copyright notice, 13 | ## this list of conditions and the following disclaimer in the documentation 14 | ## and/or other materials provided with the distribution. 15 | ## 16 | ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | ## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | ## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ## ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | ## LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | ## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | ## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | ## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | ## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | ## POSSIBILITY OF SUCH DAMAGE. 27 | ################################################################################ 28 | ## $Id: Makefile.in 214 2012-05-05 00:33:31Z seungyoung.kim $ 29 | ################################################################################ 30 | 31 | ## Compiler arguments 32 | CC = @CC@ 33 | CFLAGS = @CFLAGS@ 34 | CPPFLAGS= -I../lib/qlibc/src @CPPFLAGS@ 35 | LDFLAGS = @LDFLAGS@ 36 | LIBS = ../lib/qlibc/src/libqlibcext.a ../lib/qlibc/src/libqlibc.a @LIBS@ 37 | OBJS = main.o version.o config.o daemon.o child.o pool.o mime.o \ 38 | http_main.o http_request.o http_response.o http_header.o http_auth.o \ 39 | http_method.o http_method_dav.o http_status.o http_accesslog.o \ 40 | stream.o util.o syscall.o @OPT_OBJS@ 41 | 42 | ## Make Library 43 | all: qhttpd 44 | 45 | qhttpd: ${OBJS} 46 | ${CC} ${CFLAGS} ${CPPFLAGS} ${OBJS} ${LDFLAGS} ${LIBS} -o qhttpd 47 | install -m 0755 qhttpd ../sbin/qhttpd 48 | 49 | reall: clean all 50 | 51 | clean: 52 | rm -f ${OBJS} qhttpd ../sbin/qhttpd 53 | 54 | distclean: clean 55 | rm -f Makefile 56 | 57 | ## Compile Module 58 | .SUFFIXES: .c .cpp .o 59 | 60 | .c.o: 61 | ${CC} ${CFLAGS} ${CPPFLAGS} -c -o $@ $< 62 | 63 | .cpp.o: 64 | ${CC} ${CFLAGS} ${CPPFLAGS} -c -o $@ $< 65 | 66 | -------------------------------------------------------------------------------- /src/syscall.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qHttpd - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2008-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: syscall.c 214 2012-05-05 00:33:31Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include "qhttpd.h" 32 | 33 | int sysOpen(const char *pszPath, int nFlags, mode_t nMode) 34 | { 35 | return open(pszPath, nFlags, nMode); 36 | } 37 | 38 | int sysClose(int nFd) 39 | { 40 | return close(nFd); 41 | } 42 | 43 | int sysStat(const char *pszPath, struct stat *pBuf) 44 | { 45 | return stat(pszPath, pBuf); 46 | } 47 | 48 | int sysFstat(int nFd, struct stat *pBuf) 49 | { 50 | return fstat(nFd, pBuf); 51 | } 52 | 53 | int sysUnlink(const char *pszPath) 54 | { 55 | return unlink(pszPath); 56 | } 57 | 58 | int sysRename(const char *pszOldPath, const char *pszNewPath) 59 | { 60 | return rename(pszOldPath, pszNewPath); 61 | } 62 | 63 | int sysMkdir(const char *pszPath, mode_t nMode) 64 | { 65 | return mkdir(pszPath, nMode); 66 | } 67 | 68 | int sysRmdir(const char *pszPath) 69 | { 70 | return rmdir(pszPath); 71 | } 72 | 73 | DIR *sysOpendir(const char *pszPath) 74 | { 75 | return opendir(pszPath); 76 | } 77 | 78 | struct dirent *sysReaddir(DIR *pDir) { 79 | return readdir(pDir); 80 | } 81 | 82 | int sysClosedir(DIR *pDir) 83 | { 84 | return closedir(pDir); 85 | } 86 | -------------------------------------------------------------------------------- /lib/qlibc/examples/vector_obj.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qLibc - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2010-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: vector_obj.c 77 2012-04-11 01:19:11Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "qlibc.h" 36 | 37 | int main(void) 38 | { 39 | // sample object 40 | struct sampleobj { 41 | int num; 42 | char str[10]; 43 | }; 44 | 45 | // get new vector 46 | qvector_t *vector = qvector(); 47 | 48 | // add objects 49 | int i; 50 | struct sampleobj obj; 51 | for (i = 0; i < 3; i++) { 52 | // filling object with sample data 53 | obj.num = i; 54 | sprintf(obj.str, "hello%d", i); 55 | 56 | // stack 57 | vector->add(vector, (void *)&obj, sizeof(struct sampleobj)); 58 | } 59 | 60 | // final 61 | struct sampleobj *final; 62 | final = (struct sampleobj *)vector->toarray(vector, NULL); 63 | 64 | // print out 65 | printf("Number of Objects = %zu\n", vector->size(vector)); 66 | for (i = 0; i < vector->size(vector); i++) { 67 | printf("Object%d %d, %s\n", i+1, final[i].num, final[i].str); 68 | } 69 | 70 | // release 71 | free(final); 72 | vector->free(vector); 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /src/mime.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qHttpd - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2008-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: mime.c 214 2012-05-05 00:33:31Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include "qhttpd.h" 32 | 33 | 34 | #define DEF_MIME_ENTRY "_DEF_" 35 | #define DEF_MIME_TYPE "application/octet-stream" 36 | 37 | qlisttbl_t *m_mimelist = NULL; 38 | 39 | bool mimeInit(const char *pszFilepath) 40 | { 41 | if (m_mimelist != NULL) return false; 42 | 43 | m_mimelist = qconfig_parse_file(NULL, pszFilepath, '=', true); 44 | 45 | if (m_mimelist == NULL) return false; 46 | return true; 47 | } 48 | 49 | bool mimeFree(void) 50 | { 51 | if (m_mimelist == NULL) return false; 52 | m_mimelist->free(m_mimelist); 53 | m_mimelist = NULL; 54 | return true; 55 | } 56 | 57 | const char *mimeDetect(const char *pszFilename) 58 | { 59 | if (pszFilename == NULL || m_mimelist == NULL) return DEF_MIME_TYPE; 60 | 61 | char *pszMimetype = NULL; 62 | char *pszExt = qfile_get_ext(pszFilename); 63 | if (pszExt != NULL) { 64 | qstrupper(pszExt); 65 | pszMimetype = (char *)m_mimelist->getstr(m_mimelist, pszExt, false); 66 | free(pszExt); 67 | } 68 | 69 | if (pszMimetype == NULL) { 70 | pszMimetype = (char *)m_mimelist->getstr(m_mimelist, DEF_MIME_ENTRY, false); 71 | if (pszMimetype == NULL) pszMimetype = DEF_MIME_TYPE; 72 | } 73 | 74 | return pszMimetype; 75 | } 76 | -------------------------------------------------------------------------------- /src/version.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qHttpd - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2008-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: version.c 214 2012-05-05 00:33:31Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include "qhttpd.h" 32 | 33 | void printUsages(void) 34 | { 35 | printVersion(); 36 | fprintf(stderr, "Usage: %s [-dDVh] [-c configfile]\n", g_prgname); 37 | fprintf(stderr, " -c filepath Set configuration file.\n"); 38 | fprintf(stderr, " -d Run as debugging mode.\n"); 39 | fprintf(stderr, " -D Do not daemonize.\n"); 40 | fprintf(stderr, " -V Version info.\n"); 41 | fprintf(stderr, " -h Display this help message and exit.\n"); 42 | } 43 | 44 | void printVersion(void) 45 | { 46 | char *verstr = getVersion(); 47 | fprintf(stderr, "%s\n", verstr); 48 | free(verstr); 49 | } 50 | 51 | char *getVersion(void) 52 | { 53 | qvector_t *ver = qvector(); 54 | 55 | ver->addstrf(ver, "%s v%s", g_prgname, g_prgversion); 56 | 57 | #ifdef ENABLE_DEBUG 58 | ver->addstr(ver, " (DEBUG;"); 59 | #else 60 | ver->addstr(ver, " (RELEASE;"); 61 | #endif 62 | 63 | ver->addstrf(ver, " %s %s;", __DATE__, __TIME__); 64 | 65 | #ifdef ENABLE_LFS 66 | ver->addstr(ver, " --enable-lfs"); 67 | #endif 68 | 69 | #ifdef ENABLE_LUA 70 | ver->addstr(ver, " --enable-lua"); 71 | #endif 72 | 73 | #ifdef ENABLE_HOOK 74 | ver->addstr(ver, " --enable-hook"); 75 | #endif 76 | 77 | ver->addstr(ver, ")"); 78 | 79 | char *final = ver->tostring(ver); 80 | ver->free(ver); 81 | 82 | return final; 83 | } 84 | -------------------------------------------------------------------------------- /lib/qlibc/src/internal/qinternal.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qLibc - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2010-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: qinternal.c 98 2012-05-04 08:22:23Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include "qlibc.h" 40 | #include "qinternal.h" 41 | 42 | // Change two hex character to one hex value. 43 | char _q_x2c(char hex_up, char hex_low) 44 | { 45 | char digit; 46 | 47 | digit = 16 * (hex_up >= 'A' ? ((hex_up & 0xdf) - 'A') + 10 : hex_up - '0'); 48 | digit += (hex_low >= 'A' ? ((hex_low & 0xdf) - 'A') + 10 : hex_low - '0'); 49 | 50 | return digit; 51 | } 52 | 53 | char *_q_makeword(char *str, char stop) 54 | { 55 | char *word; 56 | int len, i; 57 | 58 | for (len = 0; ((str[len] != stop) && (str[len])); len++); 59 | word = (char *)malloc(sizeof(char) * (len + 1)); 60 | if (word == NULL) return NULL; 61 | 62 | for (i = 0; i < len; i++) word[i] = str[i]; 63 | word[i] = '\0'; 64 | 65 | if (str[len]) len++; 66 | for (i = len; str[i]; i++) str[i - len] = str[i]; 67 | str[i - len] = '\0'; 68 | 69 | return word; 70 | } 71 | 72 | void _q_humanOut(FILE *fp, void *data, size_t size, size_t max) 73 | { 74 | size_t i; 75 | for (i = 0; i < size && i < max; i++) { 76 | int c = ((char *)data)[i]; 77 | if (isprint(c) == 0) c = '?'; 78 | fputc(c, fp); 79 | } 80 | 81 | if (size > max) fputs("...", fp); 82 | } 83 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## qHttpd - http://www.qdecoder.org 3 | ## 4 | ## Copyright (c) 2008-2012 Seungyoung Kim. 5 | ## All rights reserved. 6 | ## 7 | ## Redistribution and use in source and binary forms, with or without 8 | ## modification, are permitted provided that the following conditions are met: 9 | ## 10 | ## 1. Redistributions of source code must retain the above copyright notice, 11 | ## this list of conditions and the following disclaimer. 12 | ## 2. Redistributions in binary form must reproduce the above copyright notice, 13 | ## this list of conditions and the following disclaimer in the documentation 14 | ## and/or other materials provided with the distribution. 15 | ## 16 | ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | ## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | ## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ## ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | ## LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | ## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | ## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | ## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | ## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | ## POSSIBILITY OF SUCH DAMAGE. 27 | ################################################################################ 28 | ## $Id: Makefile.in 216 2012-05-07 21:01:37Z seungyoung.kim $ 29 | ################################################################################ 30 | 31 | prefix = @prefix@ 32 | 33 | RM = @RM@ 34 | 35 | all: 36 | @for DIR in lib src; do \ 37 | echo "===> $${DIR}"; \ 38 | (cd $${DIR}; make all); \ 39 | echo "<=== $${DIR}"; \ 40 | done 41 | 42 | install: all 43 | install -d ${prefix} 44 | install -d ${prefix}/sbin 45 | install -m 0755 sbin/qhttpd ${prefix}/sbin/qhttpd 46 | install -d ${prefix}/conf 47 | install -m 0644 conf/qhttpd.conf.dist ${prefix}/conf/qhttpd.conf.dist 48 | install -m 0644 conf/mimetypes.conf ${prefix}/conf/mimetypes.conf 49 | install -m 0644 conf/qhttpd.lua.dist ${prefix}/conf/qhttpd.lua.dist 50 | install -d ${prefix}/htdocs 51 | install -m 0644 htdocs/index.html ${prefix}/htdocs/index.html 52 | install -d ${prefix}/logs 53 | 54 | deinstall: uninstall 55 | uninstall: 56 | ${RM} -f ${prefix}/sbin/qhttpd 57 | ${RM} -f ${prefix}/conf/qhttpd.conf.dist 58 | ${RM} -f ${prefix}/conf/mimetypes.conf 59 | ${RM} -f ${prefix}/conf/qhttpd.lua.dist 60 | ${RM} -f ${prefix}/htdocs/index.html 61 | 62 | clean: 63 | @for DIR in lib src; do \ 64 | echo "===> $${DIR}"; \ 65 | (cd $${DIR}; make clean); \ 66 | echo "<=== $${DIR}"; \ 67 | done 68 | 69 | distclean: clean 70 | @for DIR in lib src; do \ 71 | echo "===> $${DIR}"; \ 72 | (cd $${DIR}; make distclean); \ 73 | echo "<=== $${DIR}"; \ 74 | done 75 | ${RM} -f Makefile 76 | ${RM} -f sbin/qhttpd 77 | ${RM} -rf autom4te.cache 78 | ${RM} -f configure.lineno config.log config.status config.h 79 | 80 | -------------------------------------------------------------------------------- /lib/qlibc/examples/Makefile.in: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## qLibc - http://www.qdecoder.org 3 | ## 4 | ## Copyright (c) 2010-2012 Seungyoung Kim. 5 | ## All rights reserved. 6 | ## 7 | ## Redistribution and use in source and binary forms, with or without 8 | ## modification, are permitted provided that the following conditions are met: 9 | ## 10 | ## 1. Redistributions of source code must retain the above copyright notice, 11 | ## this list of conditions and the following disclaimer. 12 | ## 2. Redistributions in binary form must reproduce the above copyright notice, 13 | ## this list of conditions and the following disclaimer in the documentation 14 | ## and/or other materials provided with the distribution. 15 | ## 16 | ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | ## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | ## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ## ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | ## LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | ## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | ## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | ## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | ## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | ## POSSIBILITY OF SUCH DAMAGE. 27 | ################################################################################ 28 | ## $Id: Makefile.in 89 2012-04-17 00:37:52Z seungyoung.kim $ 29 | ################################################################################ 30 | 31 | prefix = @prefix@ 32 | exec_prefix = @exec_prefix@ 33 | 34 | ## Compiler options 35 | CC = @CC@ 36 | CFLAGS = @CFLAGS@ 37 | CPPFLAGS = -I../src/ @CPPFLAGS@ 38 | RM = @RM@ 39 | DEPLIBS = @DEPLIBS@ 40 | 41 | TARGETS1 = list listtbl hashtbl hasharr vector vector_obj queue stack config 42 | TARGETS2 = list listtbl hashtbl hasharr vector vector_obj queue stack 43 | TARGETS = ${@EXAMPLES_TARGETS@} 44 | LIBQLIBC = ../src/libqlibc.a ${DEPLIBS} 45 | LIBQLIBCEXT = ../src/libqlibcext.a 46 | 47 | ## Main 48 | all: ${TARGETS} 49 | 50 | list: list.o 51 | ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ list.o ${LIBQLIBC} 52 | 53 | listtbl: listtbl.o 54 | ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ listtbl.o ${LIBQLIBC} 55 | 56 | hashtbl: hashtbl.o 57 | ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ hashtbl.o ${LIBQLIBC} 58 | 59 | hasharr: hasharr.o 60 | ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ hasharr.o ${LIBQLIBC} 61 | 62 | vector: vector.o 63 | ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ vector.o ${LIBQLIBC} 64 | 65 | vector_obj: vector_obj.o 66 | ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ vector_obj.o ${LIBQLIBC} 67 | 68 | queue: queue.o 69 | ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ queue.o ${LIBQLIBC} 70 | 71 | stack: stack.o 72 | ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ stack.o ${LIBQLIBC} 73 | 74 | config: config.o 75 | ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ config.o ${LIBQLIBCEXT} ${LIBQLIBC} 76 | 77 | ## Clear Module 78 | clean: 79 | ${RM} -f *.o ${TARGETS} 80 | 81 | ## Compile Module 82 | .c.o: 83 | ${CC} ${CFLAGS} ${CPPFLAGS} -c -o $@ $< 84 | 85 | -------------------------------------------------------------------------------- /lib/qlibc/examples/queue.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qLibc - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2010-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: queue.c 78 2012-04-11 03:52:25Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include "qlibc.h" 38 | 39 | int main(void) 40 | { 41 | // create queue 42 | qqueue_t *queue = qqueue(); 43 | 44 | // example: integer queue 45 | queue->pushint(queue, 1); 46 | queue->pushint(queue, 2); 47 | queue->pushint(queue, 3); 48 | 49 | printf("popint(): %"PRId64"\n", queue->popint(queue)); 50 | printf("popint(): %"PRId64"\n", queue->popint(queue)); 51 | printf("popint(): %"PRId64"\n", queue->popint(queue)); 52 | 53 | // example: string queue 54 | queue->pushstr(queue, "A string"); 55 | queue->pushstr(queue, "B string"); 56 | queue->pushstr(queue, "C string"); 57 | 58 | char *str = queue->popstr(queue); 59 | printf("popstr(): %s\n", str); 60 | free(str); 61 | str = queue->popstr(queue); 62 | printf("popstr(): %s\n", str); 63 | free(str); 64 | str = queue->popstr(queue); 65 | printf("popstr(): %s\n", str); 66 | free(str); 67 | 68 | // example: object queue 69 | queue->push(queue, "A object", sizeof("A object")); 70 | queue->push(queue, "B object", sizeof("B object")); 71 | queue->push(queue, "C object", sizeof("C object")); 72 | 73 | void *obj = queue->pop(queue, NULL); 74 | printf("pop(): %s\n", (char *)obj); 75 | free(obj); 76 | obj = queue->pop(queue, NULL); 77 | printf("pop(): %s\n", (char *)obj); 78 | free(obj); 79 | obj = queue->pop(queue, NULL); 80 | printf("pop(): %s\n", (char *)obj); 81 | free(obj); 82 | 83 | // release 84 | queue->free(queue); 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /lib/qlibc/examples/stack.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qLibc - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2010-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: stack.c 78 2012-04-11 03:52:25Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include "qlibc.h" 38 | 39 | int main(void) 40 | { 41 | // create stack 42 | qstack_t *stack = qstack(); 43 | 44 | // example: integer stack 45 | stack->pushint(stack, 1); 46 | stack->pushint(stack, 2); 47 | stack->pushint(stack, 3); 48 | 49 | printf("popint(): %"PRId64"\n", stack->popint(stack)); 50 | printf("popint(): %"PRId64"\n", stack->popint(stack)); 51 | printf("popint(): %"PRId64"\n", stack->popint(stack)); 52 | 53 | // example: string stack 54 | stack->pushstr(stack, "A string"); 55 | stack->pushstr(stack, "B string"); 56 | stack->pushstr(stack, "C string"); 57 | 58 | char *str = stack->popstr(stack); 59 | printf("popstr(): %s\n", str); 60 | free(str); 61 | str = stack->popstr(stack); 62 | printf("popstr(): %s\n", str); 63 | free(str); 64 | str = stack->popstr(stack); 65 | printf("popstr(): %s\n", str); 66 | free(str); 67 | 68 | // example: object stack 69 | stack->push(stack, "A object", sizeof("A object")); 70 | stack->push(stack, "B object", sizeof("B object")); 71 | stack->push(stack, "C object", sizeof("C object")); 72 | 73 | void *obj = stack->pop(stack, NULL); 74 | printf("pop(): %s\n", (char *)obj); 75 | free(obj); 76 | obj = stack->pop(stack, NULL); 77 | printf("pop(): %s\n", (char *)obj); 78 | free(obj); 79 | obj = stack->pop(stack, NULL); 80 | printf("pop(): %s\n", (char *)obj); 81 | free(obj); 82 | 83 | // release 84 | stack->free(stack); 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /lib/qlibc/examples/hasharr.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qLibc - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2010-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: hasharr.c 81 2012-04-12 01:01:34Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "qlibc.h" 36 | 37 | int main(void) 38 | { 39 | // initialize hash-table 40 | char memory[1000 * 10]; 41 | qhasharr_t *tbl = qhasharr(memory, sizeof(memory)); 42 | if (tbl == NULL) { 43 | return -1; 44 | } 45 | 46 | // 47 | // TEST 1 : adding elements. 48 | // 49 | 50 | // insert elements (key duplication is not allowed) 51 | tbl->putstr(tbl, "e1", "a"); 52 | tbl->putstr(tbl, "e2", "b"); 53 | tbl->putstr(tbl, "e2", "c"); 54 | tbl->putstr(tbl, "e3", "d"); 55 | tbl->putstr(tbl, "e4", "e"); 56 | tbl->putstr(tbl, "e5", "f"); 57 | tbl->putstr(tbl, "12345678901234567890", 58 | "1234567890123456789012345678901234567890"); 59 | 60 | // print out 61 | printf("--[Test 1 : adding elements]--\n"); 62 | tbl->debug(tbl, stdout); 63 | 64 | // 65 | // TEST 2 : many ways to find key. 66 | // 67 | 68 | printf("\n--[Test 2 : many ways to find key]--\n"); 69 | char *e2 = tbl->getstr(tbl, "e2"); 70 | if (e2 != NULL) { 71 | printf("getstr('e2') : %s\n", e2); 72 | free(e2); 73 | } 74 | 75 | // 76 | // TEST 3 : travesal table. 77 | // 78 | 79 | printf("\n--[Test 3 : travesal table]--\n"); 80 | printf("table size : %d elements\n", tbl->size(tbl, NULL, NULL)); 81 | int idx = 0; 82 | qnobj_t obj; 83 | while (tbl->getnext(tbl, &obj, &idx) == true) { 84 | printf("NAME=%s, DATA=%s, SIZE=%zu\n", 85 | obj.name, (char *)obj.data, obj.size); 86 | free(obj.name); 87 | free(obj.data); 88 | } 89 | 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /lib/qlibc/examples/hashtbl.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qLibc - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2010-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: hashtbl.c 77 2012-04-11 01:19:11Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "qlibc.h" 36 | 37 | int main(void) 38 | { 39 | // create a hash-table. 40 | qhashtbl_t *tbl = qhashtbl(3); 41 | 42 | // 43 | // TEST 1 : adding elements. 44 | // 45 | 46 | // insert elements (key duplication is not allowed) 47 | tbl->putstr(tbl, "e1", "a"); 48 | tbl->putstr(tbl, "e2", "b"); 49 | tbl->putstr(tbl, "e2", "c"); 50 | tbl->putstr(tbl, "e3", "d"); 51 | tbl->putstr(tbl, "e4", "e"); 52 | tbl->putstr(tbl, "e5", "f"); 53 | 54 | // print out 55 | printf("--[Test 1 : adding elements]--\n"); 56 | tbl->debug(tbl, stdout); 57 | 58 | // 59 | // TEST 2 : many ways to find a key. 60 | // 61 | 62 | printf("\n--[Test 2 : many ways to find a key]--\n"); 63 | printf("get('e2') : %s\n", (char *)tbl->get(tbl, "e2", NULL, false)); 64 | printf("getstr('e2') : %s\n", tbl->getstr(tbl, "e2", false)); 65 | 66 | char *e2 = tbl->getstr(tbl, "e2", true); 67 | printf("getstr('e2') with newmem parameter: %s\n", e2); 68 | free(e2); 69 | 70 | // 71 | // TEST 3 : travesal a table. 72 | // 73 | 74 | printf("\n--[Test 3 : travesal a table]--\n"); 75 | printf("list size : %zu elements\n", tbl->size(tbl)); 76 | qhnobj_t obj; 77 | memset((void *)&obj, 0, sizeof(obj)); // must be cleared before call 78 | tbl->lock(tbl); 79 | while (tbl->getnext(tbl, &obj, true) == true) { 80 | printf("NAME=%s, DATA=%s, SIZE=%zu\n", 81 | obj.name, (char *)obj.data, obj.size); 82 | free(obj.name); 83 | free(obj.data); 84 | } 85 | tbl->unlock(tbl); 86 | 87 | // free object 88 | tbl->free(tbl); 89 | 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /src/http_auth.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qHttpd - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2008-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: http_auth.c 214 2012-05-05 00:33:31Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include "qhttpd.h" 32 | 33 | struct HttpUser *httpAuthParse(struct HttpRequest *pReq) { 34 | const char *pszAuthHeader = httpHeaderGetStr(pReq->pHeaders, "AUTHORIZATION"); 35 | if (IS_EMPTY_STRING(pszAuthHeader) == true) { 36 | // no auth header 37 | return NULL; 38 | } 39 | 40 | if (!strncasecmp(pszAuthHeader, "Basic ", CONST_STRLEN("Basic "))) { 41 | struct HttpUser *pHttpUser = (struct HttpUser *)malloc(sizeof(struct HttpUser)); 42 | memset((void *)pHttpUser, 0, sizeof(struct HttpUser)); 43 | pHttpUser->nAuthType = HTTP_AUTH_BASIC; 44 | 45 | // get data 46 | char *pszDecBase64 = strdup(pszAuthHeader + CONST_STRLEN("Basic ")); 47 | if (IS_EMPTY_STRING(pszDecBase64) == true) { 48 | // empty auth string 49 | if (pszDecBase64 != NULL) free(pszDecBase64); 50 | return pHttpUser; 51 | } 52 | 53 | // parse data 54 | qbase64_decode(pszDecBase64); 55 | char *pszColon = strstr(pszDecBase64, ":"); 56 | if (pszColon == NULL) { 57 | qstrcpy(pHttpUser->szUser, sizeof(pHttpUser->szUser), pszDecBase64); 58 | } else { 59 | *pszColon = '\0'; 60 | qstrcpy(pHttpUser->szUser, sizeof(pHttpUser->szUser), pszDecBase64); 61 | qstrcpy(pHttpUser->szPassword, sizeof(pHttpUser->szPassword), pszColon + 1); 62 | } 63 | 64 | DEBUG("Auth BASIC : %s/%s", pHttpUser->szUser, pHttpUser->szPassword); 65 | 66 | free(pszDecBase64); 67 | return pHttpUser; 68 | } else if (!strncasecmp(pszAuthHeader, "Digest ", CONST_STRLEN("Digest "))) { 69 | // not supported yet 70 | return NULL; 71 | } 72 | 73 | // not supported auth type 74 | return NULL; 75 | } 76 | -------------------------------------------------------------------------------- /conf/qhttpd.conf.dist: -------------------------------------------------------------------------------- 1 | ## 2 | ## This is the main qHttpd configuration file. It contains the 3 | ## configuration directives that give the server its instructions. 4 | ## See for detailed information. 5 | ## 6 | ## $Id: qhttpd.conf.dist 201 2011-01-21 03:31:22Z seungyoung.kim $ 7 | 8 | ## These are variables and not configuration mandatory entries. 9 | BaseDir = /usr/local/qhttpd 10 | ConfDir = ${BaseDir}/conf 11 | LogDir = ${BaseDir}/logs 12 | RunDir = /var/run 13 | 14 | ## PidFile: The file in which the server should record its process 15 | ## identification number when it starts. 16 | PidFile = ${RunDir}/qhttpd.pid 17 | 18 | ## MimeFile: The location of the mime-types file. 19 | MimeFile = ${ConfDir}/mimetypes.conf 20 | 21 | ## Port: listening port to serve. 22 | Port = 80 23 | 24 | ## StartServers: number of server processes to start. 25 | ## MinSpareServers: minimum number of server processes which are kept spare. 26 | ## MaxSpareServers: maximum number of server processes which are kept spare. 27 | ## MaxIdleSeconds: maximum number of seconds which idle server process waits. 28 | ## MaxClients: maximum number of server processes allowed to start. 29 | ## MaxRequestsPerChild: maximum number of requests a server process serves. 30 | StartServers = 5 31 | MinSpareServers = 3 32 | MaxSpareServers = 10 33 | MaxIdleSeconds = 300 34 | MaxClients = 150 35 | MaxRequestsPerChild = 3000 36 | 37 | ## EnableKeepAlive: Whether or not to allow persistent connections. 38 | ## MaxKeepAliveRequests: The maximum number of requests to allow 39 | ## during a persistent connection. Set to 0 to allow an unlimited amount. 40 | EnableKeepAlive = YES 41 | MaxKeepAliveRequests = 100 42 | 43 | ## ConnectionTimeout: Number of seconds to wait for the request from the 44 | ## same client on the same connection. Also used for Keep-Alive timeout. 45 | ConnectionTimeout = 10 46 | 47 | ## IgnoreOverConnection: allows to handle over coming connections 48 | ## than MaxClients setting. set to YES to response 503(SERVICE_UNAVAILABLE) 49 | ## and drop over coming connections immediately. 50 | IgnoreOverConnection = NO 51 | 52 | ## ResponseExpires: number of seconds of contents expiration. 53 | ## Cache-Control and Expires response headers will be appended, if it's 54 | ## greater than 0. Set to 0 to deactivate. 55 | ResponseExpires = 0 56 | 57 | ## DocumentRoot: The directory out of which you will serve your 58 | ## documents. By default, all requests are taken from this directory. 59 | DocumentRoot = ${BaseDir}/htdocs 60 | 61 | ## AllowedMethods: List up methods you want to activate. 62 | ## Set to "ALL" to activate all supported methods. 63 | ## - HTTP methods : OPTIONS,HEAD,GET,PUT 64 | ## - Extended methods : PROPFIND,PROPPATCH,MKCOL,MOVE,DELETE,LOCK,UNLOCK 65 | AllowedMethods = ALL 66 | #AllowedMethods = OPTIONS,HEAD,GET 67 | #AllowedMethods = OPTIONS,HEAD,GET,PUT,PROPFIND,PROPPATCH,MKCOL,MOVE,DELETE,LOCK,UNLOCK 68 | 69 | ## DirectoryIndex: sets the filename that will be served if a 70 | ## directory is requested. Set to empty to disable. 71 | DirectoryIndex = index.html 72 | 73 | ## EnableLua: Whether or not to allow LUA script engine. 74 | ## LuaScript: The file which contains LUA script for hooking connection. 75 | EnableLua = NO 76 | LuaScript = ${ConfDir}/qhttpd.lua 77 | 78 | ## EnableStatus: Whether or not to allow server status reports. 79 | ## StatusUrl: The URL for retrieving server status reports. 80 | EnableStatus = YES 81 | StatusUrl = /server-status 82 | 83 | ## ErrorLog: The location of the error log file. 84 | ## AccessLog: The location of the access log file. 85 | ## LogRotate: The time period for automatic log file rotation. 86 | ## LogLevel: Control the number of messages logged to the ErrorLog. 87 | ## 0:SYSTEM, 1:ERROR, 2:WARNING, 3:INFO, 4:DEBUG 88 | ErrorLog = ${LogDir}/qhttpd-%Y%m%d.err 89 | AccessLog = ${LogDir}/qhttpd-%Y%m%d.log 90 | LogRotate = 86400 91 | LogLevel = 2 92 | -------------------------------------------------------------------------------- /lib/qlibc/src/utilities/qsystem.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qLibc - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2010-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: qsystem.c 102 2012-05-05 00:22:27Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | /** 32 | * @file qsystem.c System APIs. 33 | */ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include "qlibc.h" 45 | #include "qinternal.h" 46 | 47 | /** 48 | * Get system environment variable 49 | * 50 | * @param envname environment name 51 | * @param nullstr if not found, return this string 52 | * 53 | * @return a pointer of environment variable 54 | */ 55 | const char *qgetenv(const char *envname, const char *nullstr) 56 | { 57 | const char *envstr = getenv(envname); 58 | if (envstr != NULL) return envstr; 59 | return nullstr; 60 | } 61 | 62 | /** 63 | * Get the result string of external command execution 64 | * 65 | * @param cmd external command 66 | * 67 | * @return malloced string pointer which contains result if successful, 68 | * otherwise returns NULL 69 | * 70 | * @note 71 | * If the command does not report result but it is executed successfully, 72 | * this will returns empty string(not null) 73 | */ 74 | char *qsyscmd(const char *cmd) 75 | { 76 | FILE *fp = popen(cmd, "r"); 77 | if (fp == NULL) return NULL; 78 | char *str = qfile_read(fp, NULL); 79 | pclose(fp); 80 | 81 | if (str == NULL) str = strdup(""); 82 | return str; 83 | } 84 | 85 | /** 86 | * Get system IP address string. 87 | * 88 | * @return malloced string pointer which contains IP address string if 89 | * successful, otherwise returns NULL 90 | */ 91 | bool qsysgetip(char *buf, size_t bufsize) 92 | { 93 | char szHostname[63+1]; 94 | if (gethostname(szHostname, sizeof(szHostname)) != 0) return false; 95 | 96 | struct hostent *pHostEntry = gethostbyname(szHostname); 97 | if (pHostEntry == NULL) return false; 98 | 99 | char *pszLocalIp = inet_ntoa(*(struct in_addr *)*pHostEntry->h_addr_list); 100 | if (pszLocalIp == NULL) return false; 101 | 102 | qstrcpy(buf, bufsize, pszLocalIp); 103 | return true; 104 | } 105 | -------------------------------------------------------------------------------- /lib/qlibc/examples/list.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qLibc - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2010-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: list.c 77 2012-04-11 01:19:11Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "qlibc.h" 36 | 37 | int main(void) 38 | { 39 | // create a list. 40 | qlist_t *list = qlist(); 41 | 42 | // 43 | // TEST 1 : adding elements. 44 | // 45 | 46 | // insert elements 47 | list->addlast(list, "e1", sizeof("e1")); 48 | list->addlast(list, "e2", sizeof("e2")); 49 | list->addlast(list, "e3", sizeof("e3")); 50 | list->addfirst(list, "e4", sizeof("e4")); 51 | list->addfirst(list, "e5", sizeof("e5")); 52 | 53 | // print out 54 | printf("--[Test 1 : adding elements]--\n"); 55 | list->debug(list, stdout); 56 | 57 | // 58 | // TEST 2 : get methods 59 | // 60 | 61 | printf("\n--[Test 2 : get methods]--\n"); 62 | printf("getFirst() : %s\n", (char *)list->getfirst(list, NULL, false)); 63 | printf("getLast() : %s\n", (char *)list->getlast(list, NULL, false)); 64 | printf("getAt(0) : %s\n", (char *)list->getat(list, 0, NULL, false)); 65 | printf("getAt(5) : %s\n", (char *)list->getat(list, 4, NULL, false)); 66 | printf("getAt(-1) : %s\n", (char *)list->getat(list, -1, NULL, false)); 67 | printf("getAt(-2) : %s\n", (char *)list->getat(list, -2, NULL, false)); 68 | 69 | // 70 | // TEST 3 : pop methods 71 | // 72 | 73 | printf("\n--[Test 3 : pop(get and remove) methods]--\n"); 74 | char *first = (char *)list->popfirst(list, NULL); 75 | char *last = (char *)list->poplast(list, NULL); 76 | printf("popFirst() : %s\n", first); 77 | printf("popLast() : %s\n", last); 78 | free(first); 79 | free(last); 80 | 81 | list->debug(list, stdout); 82 | 83 | // 84 | // TEST 4 : travesal list. 85 | // 86 | 87 | printf("\n--[Test 4 : travesal list]--\n"); 88 | printf("list size : %zu elements\n", list->size(list)); 89 | qdlobj_t obj; 90 | memset((void *)&obj, 0, sizeof(obj)); // must be cleared before call 91 | list->lock(list); 92 | while (list->getnext(list, &obj, false) == true) { 93 | printf("DATA=%s, SIZE=%zu\n", (char *)obj.data, obj.size); 94 | } 95 | list->unlock(list); 96 | 97 | // 98 | // TEST 5 : reverse list 99 | // 100 | 101 | list->reverse(list); 102 | 103 | // print out 104 | printf("\n--[Test 5 : reverse]--\n"); 105 | list->debug(list, stdout); 106 | 107 | // free object 108 | list->free(list); 109 | 110 | return 0; 111 | } 112 | -------------------------------------------------------------------------------- /lib/qlibc/src/utilities/qcount.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qLibc - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2010-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: qcount.c 88 2012-04-17 00:23:20Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | /** 32 | * @file qcount.c Counter file handling APIs. 33 | */ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include "qlibc.h" 46 | #include "qinternal.h" 47 | 48 | /** 49 | * Read counter(integer) from file with advisory file locking. 50 | * 51 | * @param filepath file path 52 | * 53 | * @return counter value readed from file. in case of failure, returns 0. 54 | * 55 | * @code 56 | * qcount_save("number.dat", 75); 57 | * int count = qcount_read("number.dat"); 58 | * @endcode 59 | * 60 | * @code 61 | * ---- number.dat ---- 62 | * 75 63 | * -------------------- 64 | * @endcode 65 | */ 66 | int64_t qcount_read(const char *filepath) 67 | { 68 | int fd = open(filepath, O_RDONLY, 0); 69 | if (fd < 0) return 0; 70 | 71 | char buf[20+1]; 72 | ssize_t readed = read(fd, buf, (sizeof(buf) - 1)); 73 | close(fd); 74 | 75 | int64_t num = 0; 76 | if (readed > 0) { 77 | buf[readed] = '\0'; 78 | num = atoll(buf); 79 | } 80 | 81 | return num; 82 | } 83 | 84 | /** 85 | * Save counter(integer) to file with advisory file locking. 86 | * 87 | * @param filepath file path 88 | * @param number counter integer value 89 | * 90 | * @return true if successful, otherwise returns false. 91 | * 92 | * @code 93 | * qcount_save("number.dat", 75); 94 | * @endcode 95 | */ 96 | bool qcount_save(const char *filepath, int64_t number) 97 | { 98 | int fd = open(filepath, O_CREAT|O_WRONLY|O_TRUNC, DEF_FILE_MODE); 99 | if (fd < 0) return false; 100 | 101 | char *str = qstrdupf("%"PRId64, number); 102 | ssize_t updated = write(fd, str, strlen(str)); 103 | close(fd); 104 | 105 | if (updated > 0) return true; 106 | return false; 107 | } 108 | 109 | /** 110 | * Increases(or decrease) the counter value as much as specified number 111 | * with advisory file locking. 112 | * 113 | * @param filepath file path 114 | * @param number how much increase or decrease 115 | * 116 | * @return updated counter value. in case of failure, returns 0. 117 | * 118 | * @code 119 | * int count; 120 | * count = qcount_update("number.dat", -3); 121 | * @endcode 122 | */ 123 | int64_t qcount_update(const char *filepath, int64_t number) 124 | { 125 | int64_t counter = qcount_read(filepath); 126 | counter += number; 127 | if (qcount_save(filepath, counter) == true) { 128 | return counter; 129 | } 130 | return 0; 131 | } 132 | -------------------------------------------------------------------------------- /src/http_header.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qHttpd - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2008-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: http_header.c 214 2012-05-05 00:33:31Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include "qhttpd.h" 32 | 33 | const char *httpHeaderGetStr(qlisttbl_t *entries, const char *pszName) 34 | { 35 | return entries->getstr(entries, pszName, false); 36 | } 37 | 38 | int httpHeaderGetInt(qlisttbl_t *entries, const char *pszName) 39 | { 40 | return entries->getint(entries, pszName); 41 | } 42 | 43 | bool httpHeaderSetStr(qlisttbl_t *entries, const char *pszName, const char *pszValue) 44 | { 45 | if (pszValue != NULL) entries->putstr(entries, pszName, pszValue, true); 46 | else entries->remove(entries, pszName); 47 | 48 | return true; 49 | } 50 | 51 | bool httpHeaderSetStrf(qlisttbl_t *entries, const char *pszName, const char *pszFormat, ...) 52 | { 53 | char *pszValue; 54 | DYNAMIC_VSPRINTF(pszValue, pszFormat); 55 | if (pszValue == NULL) return false; 56 | 57 | bool bRet = httpHeaderSetStr(entries, pszName, pszValue); 58 | free(pszValue); 59 | 60 | return bRet; 61 | } 62 | 63 | bool httpHeaderRemove(qlisttbl_t *entries, const char *pszName) 64 | { 65 | if (entries->remove(entries, pszName) > 0) return true; 66 | return false; 67 | } 68 | 69 | bool httpHeaderHasCasestr(qlisttbl_t *entries, const char *pszName, const char *pszValue) 70 | { 71 | const char *pszVal = entries->getstr(entries, pszName, false); 72 | if (pszVal == NULL) return false; 73 | 74 | if (strcasestr(pszVal, pszValue) != NULL) return true; 75 | return false; 76 | } 77 | 78 | bool httpHeaderParseRange(const char *pszRangeHeader, off_t nFilesize, off_t *pnRangeOffset1, off_t *pnRangeOffset2, off_t *pnRangeSize) 79 | { 80 | if (pszRangeHeader == NULL) return false; 81 | 82 | char *pszRange = strdup(pszRangeHeader); 83 | char *p1, *p2, *p3; 84 | 85 | p1 = strstr(pszRange, "="); 86 | p2 = strstr(pszRange, "-"); 87 | p3 = strstr(pszRange, ","); 88 | 89 | // grammer check 90 | if (p1 == NULL || p2 == NULL || p2 < p1) { 91 | free(pszRange); 92 | return false; 93 | } 94 | 95 | // multi-range is not supported 96 | if (p3 == NULL) p3 = pszRange + strlen(pszRange); 97 | else *p3 = '\0'; 98 | 99 | // parse 100 | p1 += 1; 101 | *p2 = '\0'; 102 | 103 | // start 104 | if (p1 == p2) *pnRangeOffset1 = 0; 105 | else *pnRangeOffset1 = (off_t)atoll(p1); 106 | 107 | // end 108 | p2 += 1; 109 | if (p2 == p3) *pnRangeOffset2 = nFilesize - 1; 110 | else *pnRangeOffset2 = (off_t)atoll(p2); 111 | 112 | *pnRangeSize = (*pnRangeOffset2 - *pnRangeOffset1) + 1; 113 | free(pszRange); 114 | 115 | if (*pnRangeOffset1 > *pnRangeOffset2) return false; 116 | return true; 117 | } 118 | 119 | bool httpHeaderSetExpire(qlisttbl_t *entries, int nExpire) 120 | { 121 | // cache control 122 | if (nExpire > 0) { 123 | httpHeaderSetStrf(entries, "Cache-Control", "max-age=%d", nExpire); 124 | httpHeaderSetStrf(entries, "Expires", "%s", qtime_gmt_staticstr(time(NULL) + nExpire)); 125 | return true; 126 | } 127 | 128 | return false; 129 | } 130 | -------------------------------------------------------------------------------- /conf/qhttpd.lua.dist: -------------------------------------------------------------------------------- 1 | --============================================================================= 2 | -- This script will be loaded everytime each childs launched. 3 | -- And once it is loaded, it will be used until child terminated. 4 | -- 5 | -- So it is possible that storing request information or some of your 6 | -- informations to temporary global variable in the requestHandler() 7 | -- then using stored information in responseHandler(). 8 | -- 9 | -- This script is called sequencially so race condition does not occured. 10 | -- 11 | -- * Supported functions 12 | -- + [http] functions 13 | -- string http:getRemoteAddr() : returns remote IP address as string 14 | -- number http:getRemotePort() : returns remote port as integer 15 | -- 16 | -- + [request] functions 17 | -- table request:getRequest() : get request information table 18 | -- boolean request:setRequest(request_table) : set/modify request information 19 | -- string request:getHeader(name) : get request header 20 | -- boolean request:setHeader(name, value) : set request header 21 | -- boolean request:delHeader(name) : remove request header 22 | -- 23 | -- + [response] functions 24 | -- number response:getCode() : get response code 25 | -- boolean response:setCode() : set response code 26 | -- boolean response:setContent(mimetype, content) : set response content 27 | -- string response:getHeader(name) : get response header 28 | -- boolean response:setHeader(name, value) : set requresponseest header 29 | -- boolean response:delHeader(name) : remove response header 30 | -- 31 | -- + control 32 | -- void http:terminate() : terminate this child after processing this session 33 | -- 34 | -- * Data structure 35 | -- - request table = {requestMethod=, requestHost=, requestPath=, queryString= } 36 | -- 37 | -- $Id: qhttpd.lua.dist 201 2011-01-21 03:31:22Z seungyoung.kim $ 38 | --============================================================================= 39 | 40 | --============================================================================= 41 | -- Hook request - called after parsing request header 42 | -- @return response code(number type) 43 | -- 44 | -- If you return response code like 200, native method handler will not be called. 45 | -- So if want to continue routines (almost case), please return 0. 46 | --============================================================================= 47 | function requestHandler() 48 | 49 | return 0; 50 | end 51 | 52 | --============================================================================= 53 | -- Hook response - called before responding out 54 | -- @return response code(number type) 55 | --============================================================================= 56 | function responseHandler() 57 | 58 | return 0; 59 | end 60 | 61 | --============================================================================= 62 | -- Initializing codes and global variables here 63 | --============================================================================= 64 | 65 | 66 | 67 | 68 | 69 | 70 | --============================================================================= 71 | -- SAMPLE: responding 200 with text/plain message immediately 72 | --============================================================================= 73 | --function requestHandler() 74 | -- nResCode = 200; 75 | -- http:setContent("text/plain", "hello world"); 76 | -- return nResCode; 77 | --end 78 | -- 79 | --============================================================================= 80 | -- SAMPLE : log request 81 | --============================================================================= 82 | --function requestHandler() 83 | -- local req = request:getRequest(); 84 | -- if (req ~= nil) then 85 | -- out = assert(io.open("/tmp/lua.out", "a+")); 86 | -- out:write("req.requestMethod = ",req.requestMethod,"\n"); 87 | -- out:write("req.requestHost = ",req.requestHost,"\n"); 88 | -- out:write("req.requestPath = ",req.requestPath,"\n"); 89 | -- out:write("req.queryString = ",req.queryString,"\n"); 90 | -- out:write("Remote Addr = ",http:getRemoteAddr(),":",http:getRemotePort(),"\n"); 91 | -- out:write("User-Agent = ", request:getHeader("USER-AGENT"),"\n"); 92 | -- out:write("\n"); 93 | -- out:close(); 94 | -- end 95 | -- 96 | -- return 0; 97 | --end 98 | -- 99 | --============================================================================= 100 | -- SAMPLE : modifing respose header 101 | --============================================================================= 102 | --function responseHandler() 103 | -- local code = response:getCode(); 104 | -- 105 | -- out = assert(io.open("/tmp/lua.out", "a+")); 106 | -- out:write("Response Code = ",code,"\n"); 107 | -- out:write("\n"); 108 | -- out:close(); 109 | -- 110 | -- if (code == 200) then 111 | -- response:setHeader("Server", "milk/1.0.0"); 112 | -- end 113 | -- 114 | -- -- to re-load script for debugging purpose. 115 | -- -- must be comment out 116 | -- http:terminate() 117 | -- 118 | -- return 0; 119 | --end 120 | -------------------------------------------------------------------------------- /src/stream.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qHttpd - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2008-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: stream.c 214 2012-05-05 00:33:31Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include "qhttpd.h" 32 | 33 | ssize_t streamRead(int nSockFd, void *pszBuffer, size_t nSize, int nTimeoutMs) 34 | { 35 | ssize_t nReaded = qio_read(nSockFd, pszBuffer, nSize, nTimeoutMs); 36 | #ifdef ENABLE_DEBUG 37 | if (nReaded > 0) DEBUG("[RX] (binary, readed %zd bytes)", nReaded); 38 | #endif 39 | return nReaded; 40 | } 41 | 42 | ssize_t streamGets(int nSockFd, char *pszStr, size_t nSize, int nTimeoutMs) 43 | { 44 | ssize_t nReaded = qio_gets(nSockFd, pszStr, nSize, nTimeoutMs); 45 | #ifdef ENABLE_DEBUG 46 | if (nReaded > 0) DEBUG("[RX] %s", pszStr); 47 | #endif 48 | return nReaded; 49 | } 50 | 51 | ssize_t streamGetb(int nSockFd, char *pszBuffer, size_t nSize, int nTimeoutMs) 52 | { 53 | ssize_t nReaded = qio_read(nSockFd, pszBuffer, nSize, nTimeoutMs); 54 | DEBUG("[RX] (binary, readed/request=%zd/%zu bytes)", nReaded, nSize); 55 | return nReaded; 56 | } 57 | 58 | off_t streamSave(int nFd, int nSockFd, off_t nSize, int nTimeoutMs) 59 | { 60 | off_t nSaved = qio_send(nFd, nSockFd, nSize, nTimeoutMs); 61 | DEBUG("[RX] (save %jd/%jd bytes)", nSaved, nSize); 62 | return nSaved; 63 | } 64 | 65 | ssize_t streamPrintf(int nSockFd, const char *format, ...) 66 | { 67 | char *pszBuf; 68 | DYNAMIC_VSPRINTF(pszBuf, format); 69 | if (pszBuf == NULL) return -1; 70 | 71 | ssize_t nSent = qio_write(nSockFd, pszBuf, strlen(pszBuf), 0); 72 | 73 | #ifdef ENABLE_DEBUG 74 | if (nSent > 0) DEBUG("[TX] %s", pszBuf); 75 | else DEBUG("[TX-ERR] %s", pszBuf); 76 | #endif 77 | free(pszBuf); 78 | 79 | return nSent; 80 | } 81 | 82 | ssize_t streamPuts(int nSockFd, const char *pszStr) 83 | { 84 | ssize_t nSent = qio_puts(nSockFd, pszStr, 0); 85 | 86 | #ifdef ENABLE_DEBUG 87 | if (nSent > 0) DEBUG("[TX] %s", pszStr); 88 | else DEBUG("[TX-ERR] %s", pszStr); 89 | #endif 90 | 91 | return nSent; 92 | } 93 | 94 | ssize_t streamStackOut(int nSockFd, qvector_t *vector, int nTimeoutMs) 95 | { 96 | size_t nSize; 97 | char *pData = (char *)vector->toarray(vector, &nSize); 98 | 99 | ssize_t nWritten = 0; 100 | if (pData != NULL) { 101 | nWritten = qio_write(nSockFd, pData, nSize, nTimeoutMs); 102 | 103 | #ifdef ENABLE_DEBUG 104 | if (g_debug) { 105 | pData[nSize - 1] = '\0'; 106 | if (nWritten > 0) DEBUG("[TX] %s", pData); 107 | else DEBUG("[TX-ERR] %s", pData); 108 | } 109 | #endif 110 | 111 | free(pData); 112 | } 113 | 114 | return nWritten; 115 | } 116 | 117 | ssize_t streamWrite(int nSockFd, const void *pszBuffer, size_t nSize, int nTimeoutMs) 118 | { 119 | ssize_t nWritten = qio_write(nSockFd, pszBuffer, nSize, nTimeoutMs); 120 | DEBUG("[TX] (binary, written/request=%zd/%zu bytes)", nWritten, nSize); 121 | 122 | return nWritten; 123 | } 124 | 125 | ssize_t streamWritev(int nSockFd, const struct iovec *pVector, int nCount, int nTimeoutMs) 126 | { 127 | ssize_t nWritten = 0; 128 | int i; 129 | for (i = 0; i < nCount; i++) { 130 | ssize_t nSent = streamWrite(nSockFd, pVector[i].iov_base, pVector[i].iov_len, nTimeoutMs); 131 | if (nSent <= 0) break; 132 | nWritten += nSent; 133 | } 134 | 135 | /* 136 | ssize_t nWritten = writev(nSockFd, pVector, nCount); 137 | */ 138 | 139 | DEBUG("[TX] (binary, written=%zd bytes, %d vectors)", nWritten, nCount); 140 | 141 | return nWritten; 142 | } 143 | 144 | off_t streamSend(int nSockFd, int nFd, off_t nSize, int nTimeoutMs) 145 | { 146 | off_t nSent = qio_send(nSockFd, nFd, nSize, nTimeoutMs); 147 | DEBUG("[TX] (send %jd/%jd bytes)", nSent, nSize); 148 | 149 | return nSent; 150 | } 151 | -------------------------------------------------------------------------------- /src/util.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qHttpd - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2008-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: util.c 214 2012-05-05 00:33:31Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include "qhttpd.h" 32 | 33 | int closeSocket(int nSockFd) 34 | { 35 | // close connection 36 | if (shutdown(nSockFd, SHUT_WR) == 0) { 37 | char szDummyBuf[1024]; 38 | while (true) { 39 | ssize_t nDummyRead = streamRead(nSockFd, szDummyBuf, sizeof(szDummyBuf), MAX_SHUTDOWN_WAIT); 40 | if (nDummyRead <= 0) break; 41 | DEBUG("Throw %zu bytes from dummy input stream.", nDummyRead); 42 | } 43 | } 44 | return close(nSockFd); 45 | } 46 | 47 | char *getEtag(char *pszBuf, size_t nBufSize, const char *pszPath, struct stat *pStat) 48 | { 49 | unsigned int nFilepathHash = qhashfnv1_32((const void *)pszPath, strlen(pszPath)); 50 | snprintf(pszBuf, nBufSize, "%08x-%08x-%08x", nFilepathHash, (unsigned int)pStat->st_size, (unsigned int)pStat->st_mtime); 51 | pszBuf[nBufSize - 1] = '\0'; 52 | return pszBuf; 53 | } 54 | 55 | unsigned int getIp2Uint(const char *szIp) 56 | { 57 | char szBuf[15+1]; 58 | char *pszToken; 59 | int nTokenCnt = 0; 60 | unsigned int nAddr = 0; 61 | 62 | // check length 63 | if (strlen(szIp) > 15) return 0; 64 | 65 | // copy to buffer 66 | strcpy(szBuf, szIp); 67 | for (pszToken = strtok(szBuf, "."); pszToken != NULL; pszToken = strtok(NULL, ".")) { 68 | nTokenCnt++; 69 | 70 | if (nTokenCnt == 1) nAddr += (unsigned int)(atoi(pszToken)) * 0x1000000; 71 | else if (nTokenCnt == 2) nAddr += (unsigned int)(atoi(pszToken)) * 0x10000; 72 | else if (nTokenCnt == 3) nAddr += (unsigned int)(atoi(pszToken)) * 0x100; 73 | else if (nTokenCnt == 4) nAddr += (unsigned int)(atoi(pszToken)); 74 | else return 0; 75 | } 76 | if (nTokenCnt != 4) return 0; 77 | 78 | return nAddr; 79 | } 80 | 81 | float getDiffTimeval(struct timeval *t1, struct timeval *t0) 82 | { 83 | struct timeval nowt; 84 | float nDiff; 85 | 86 | if (t1 == NULL) { 87 | gettimeofday(&nowt, NULL); 88 | t1 = &nowt; 89 | } 90 | 91 | nDiff = t1->tv_sec - t0->tv_sec; 92 | if (t1->tv_usec - t0->tv_usec != 0) nDiff += (float)(t1->tv_usec - t0->tv_usec) / 1000000; 93 | 94 | //DEBUG("%ld.%ld %ld.%ld", t1->tv_sec, t1->tv_usec, t0->tv_sec, t0->tv_usec); 95 | 96 | return nDiff; 97 | } 98 | 99 | /** 100 | * validate file path 101 | */ 102 | bool isValidPathname(const char *pszPath) 103 | { 104 | if (pszPath == NULL) return false; 105 | 106 | int nLen = strlen(pszPath); 107 | if (nLen == 0 || nLen >= PATH_MAX) return false; 108 | else if (pszPath[0] != '/') return false; 109 | else if (strpbrk(pszPath, "\\:*?\"<>|") != NULL) return false; 110 | 111 | // check folder name length 112 | char *t; 113 | int n; 114 | for (n = 0, t = (char *)pszPath; *t != '\0'; t++) { 115 | if (*t == '/') { 116 | n = 0; 117 | continue; 118 | } 119 | 120 | if (n >= FILENAME_MAX) { 121 | DEBUG("Filename too long."); 122 | return false; 123 | } 124 | 125 | n++; 126 | } 127 | 128 | return true; 129 | } 130 | 131 | /** 132 | * Correting path 133 | * 134 | * @note 135 | * remove : heading & tailing white spaces, double slashes, tailing slash 136 | */ 137 | void correctPathname(char *pszPath) 138 | { 139 | // take off heading & tailing white spaces 140 | qstrtrim(pszPath); 141 | 142 | // take off double slashes 143 | while (strstr(pszPath, "//") != NULL) qstrreplace("sr", pszPath, "//", "/"); 144 | 145 | // take off tailing slash 146 | int nLen = strlen(pszPath); 147 | if (nLen <= 1) return; 148 | if (pszPath[nLen - 1] == '/') pszPath[nLen - 1] = '\0'; 149 | } 150 | -------------------------------------------------------------------------------- /lib/qlibc/src/utilities/qsocket.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qLibc - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2010-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: qsocket.c 58 2012-04-04 23:02:43Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | /** 32 | * @file qsocket.c Socket dandling APIs. 33 | */ 34 | 35 | #ifndef DISABLE_SOCKET 36 | #ifndef _WIN32 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include "qlibc.h" 51 | #include "qinternal.h" 52 | 53 | /** 54 | * Create a TCP socket for the remote host and port. 55 | * 56 | * @param hostname remote hostname 57 | * @param port remote port 58 | * @param timeoutms wait timeout milliseconds. if set to negative value, 59 | * wait indefinitely. 60 | * 61 | * @return the new socket descriptor, or 62 | * -1 in case of invalid hostname, 63 | * -2 in case of socket creation failure, 64 | * -3 in case of connection failure. 65 | */ 66 | int qsocket_open(const char *hostname, int port, int timeoutms) 67 | { 68 | /* host conversion */ 69 | struct sockaddr_in addr; 70 | if (qsocket_get_addr(&addr, hostname, port) == false) { 71 | return -1; /* invalid hostname */ 72 | } 73 | 74 | /* create new socket */ 75 | int sockfd; 76 | if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 77 | return -2; /* sockfd creation fail */ 78 | } 79 | 80 | /* set to non-block socket*/ 81 | int flags = fcntl(sockfd, F_GETFL, 0); 82 | if (timeoutms >= 0) fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); 83 | 84 | /* try to connect */ 85 | int status = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)); 86 | if ( status < 0 && (errno != EINPROGRESS 87 | || qio_wait_writable(sockfd, timeoutms) <= 0) ) { 88 | close(sockfd); 89 | return -3; /* connection failed */ 90 | } 91 | 92 | /* restore to block socket */ 93 | if (timeoutms >= 0) fcntl(sockfd, F_SETFL, flags); 94 | 95 | return sockfd; 96 | } 97 | 98 | /** 99 | * Close socket. 100 | * 101 | * @param sockfd socket descriptor 102 | * @param timeoutms if timeoutms >= 0, shut down write connection first then 103 | * wait and throw out input stream data. set to -1 to close 104 | * socket immediately. 105 | * 106 | * @return true on success, or false if an error occurred. 107 | */ 108 | bool qsocket_close(int sockfd, int timeoutms) 109 | { 110 | // close connection 111 | if (timeoutms >= 0 && shutdown(sockfd, SHUT_WR) == 0) { 112 | char buf[1024]; 113 | while (true) { 114 | ssize_t read = qio_read(sockfd, buf, sizeof(buf), timeoutms); 115 | if (read <= 0) break; 116 | DEBUG("Throw %zu bytes from dummy input stream.", read); 117 | } 118 | } 119 | 120 | if (close(sockfd) == 0) return true; 121 | return false; 122 | } 123 | 124 | /** 125 | * Convert hostname to sockaddr_in structure. 126 | * 127 | * @param addr sockaddr_in structure pointer 128 | * @param hostname IP string address or hostname 129 | * @param port port number 130 | * 131 | * @return true if successful, otherwise returns false. 132 | */ 133 | bool qsocket_get_addr(struct sockaddr_in *addr, const char *hostname, int port) 134 | { 135 | /* here we assume that the hostname argument contains ip address */ 136 | memset((void *)addr, 0, sizeof(struct sockaddr_in)); 137 | if (!inet_aton(hostname, &addr->sin_addr)) { /* fail then try another way */ 138 | struct hostent *hp; 139 | if ((hp = gethostbyname (hostname)) == 0) return false; 140 | memcpy (&addr->sin_addr, hp->h_addr, sizeof(struct in_addr)); 141 | } 142 | addr->sin_family = AF_INET; 143 | addr->sin_port = htons(port); 144 | 145 | return true; 146 | } 147 | 148 | #endif /* _WIN32 */ 149 | #endif /* DISABLE_SOCKET */ 150 | -------------------------------------------------------------------------------- /lib/qlibc/src/Makefile.in: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## qLibc - http://www.qdecoder.org 3 | ## 4 | ## Copyright (c) 2010-2012 Seungyoung Kim. 5 | ## All rights reserved. 6 | ## 7 | ## Redistribution and use in source and binary forms, with or without 8 | ## modification, are permitted provided that the following conditions are met: 9 | ## 10 | ## 1. Redistributions of source code must retain the above copyright notice, 11 | ## this list of conditions and the following disclaimer. 12 | ## 2. Redistributions in binary form must reproduce the above copyright notice, 13 | ## this list of conditions and the following disclaimer in the documentation 14 | ## and/or other materials provided with the distribution. 15 | ## 16 | ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | ## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | ## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ## ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | ## LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | ## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | ## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | ## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | ## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | ## POSSIBILITY OF SUCH DAMAGE. 27 | ################################################################################ 28 | ## $Id: Makefile.in 71 2012-04-10 10:23:48Z seungyoung.kim $ 29 | ################################################################################ 30 | 31 | prefix = @prefix@ 32 | exec_prefix = @exec_prefix@ 33 | 34 | ## System library directory 35 | LIBDIR = @libdir@ 36 | HEADERDIR = @includedir@ 37 | 38 | ## Which compiler & options for release 39 | CC = @CC@ 40 | CFLAGS = @CFLAGS@ 41 | CPPFLAGS = @CPPFLAGS@ 42 | 43 | ## Utilities 44 | AR = @AR@ 45 | ARFLAGS = -rc 46 | CHMOD = @CHMOD@ 47 | INSTALL = @INSTALL@ 48 | INSTALL_DATA = @INSTALL_DATA@ 49 | LN_S = @LN_S@ 50 | RANLIB = @RANLIB@ 51 | RM = @RM@ 52 | 53 | ## Custom definitions 54 | BUILD_TARGETS = @BUILD_TARGETS@ 55 | INSTALL_TARGETS = @INSTALL_TARGETS@ 56 | 57 | ## qlibc definitions 58 | QLIBC_LIBNAME = libqlibc.a 59 | QLIBC_SLIBNAME = libqlibc.so 60 | QLIBC_SLIBVERSION = 2 61 | QLIBC_SLIBREALNAME = ${QLIBC_SLIBNAME}.${QLIBC_SLIBVERSION} 62 | 63 | ## qlibcext definitions 64 | QLIBCEXT_LIBNAME = libqlibcext.a 65 | QLIBCEXT_SLIBNAME = libqlibcext.so 66 | QLIBCEXT_SLIBVERSION = 1 67 | QLIBCEXT_SLIBREALNAME = ${QLIBCEXT_SLIBNAME}.${QLIBCEXT_SLIBVERSION} 68 | 69 | ## Objects List 70 | QLIBC_OBJS = \ 71 | containers/qlist.o \ 72 | containers/qlisttbl.o \ 73 | containers/qhashtbl.o \ 74 | containers/qhasharr.o \ 75 | containers/qvector.o \ 76 | containers/qqueue.o \ 77 | containers/qstack.o \ 78 | \ 79 | utilities/qcount.o \ 80 | utilities/qencode.o \ 81 | utilities/qfile.o \ 82 | utilities/qhash.o \ 83 | utilities/qio.o \ 84 | utilities/qlibc.o \ 85 | utilities/qsocket.o \ 86 | utilities/qstring.o \ 87 | utilities/qsystem.o \ 88 | utilities/qtime.o \ 89 | \ 90 | ipc/qsem.o \ 91 | ipc/qshm.o \ 92 | \ 93 | internal/qinternal.o \ 94 | internal/md5/md5c.o 95 | 96 | QLIBCEXT_OBJS = \ 97 | extensions/qconfig.o \ 98 | extensions/qlog.o \ 99 | extensions/qhttpclient.o \ 100 | extensions/qdatabase.o 101 | 102 | ## Make Library 103 | all: ${BUILD_TARGETS} 104 | 105 | qlibc: ${QLIBC_OBJS} 106 | ${AR} ${ARFLAGS} ${QLIBC_LIBNAME} ${QLIBC_OBJS} 107 | ${RANLIB} ${QLIBC_LIBNAME} 108 | ${CC} -shared -Wl,-soname,${QLIBC_SLIBREALNAME} -o ${QLIBC_SLIBREALNAME} ${QLIBC_OBJS} 109 | ${LN_S} -f ${QLIBC_SLIBREALNAME} ${QLIBC_SLIBNAME} 110 | 111 | qlibcext: ${QLIBCEXT_OBJS} 112 | ${AR} ${ARFLAGS} ${QLIBCEXT_LIBNAME} ${QLIBCEXT_OBJS} 113 | ${RANLIB} ${QLIBCEXT_LIBNAME} 114 | ${CC} -shared -Wl,-soname,${QLIBCEXT_SLIBREALNAME} -o ${QLIBCEXT_SLIBREALNAME} ${QLIBCEXT_OBJS} 115 | ${LN_S} -f ${QLIBCEXT_SLIBREALNAME} ${QLIBCEXT_SLIBNAME} 116 | 117 | install: ${INSTALL_TARGETS} 118 | 119 | install-qlibc: qlibc 120 | ${INSTALL_DATA} qlibc.h ${HEADERDIR}/qlibc.h 121 | ${INSTALL_DATA} ${QLIBC_LIBNAME} ${LIBDIR}/${QLIBC_LIBNAME} 122 | ${INSTALL_DATA} ${QLIBC_SLIBREALNAME} ${LIBDIR}/${QLIBC_SLIBREALNAME} 123 | ${LN_S} -f ${LIBDIR}/${QLIBC_SLIBREALNAME} ${LIBDIR}/${QLIBC_SLIBNAME} 124 | 125 | install-qlibcext: qlibcext 126 | ${INSTALL_DATA} qlibcext.h ${HEADERDIR}/qlibcext.h 127 | ${INSTALL_DATA} ${QLIBCEXT_LIBNAME} ${LIBDIR}/${QLIBCEXT_LIBNAME} 128 | ${INSTALL_DATA} ${QLIBCEXT_SLIBREALNAME} ${LIBDIR}/${QLIBCEXT_SLIBREALNAME} 129 | ${LN_S} -f ${LIBDIR}/${QLIBCEXT_SLIBREALNAME} ${LIBDIR}/${QLIBCEXT_SLIBNAME} 130 | 131 | deinstall: uninstall 132 | uninstall: 133 | ${RM} -f ${HEADERDIR}/qlibc.h 134 | ${RM} -f ${LIBDIR}/${QLIBC_LIBNAME} 135 | ${RM} -f ${LIBDIR}/${QLIBC_SLIBREALNAME} 136 | ${RM} -f ${LIBDIR}/${QLIBC_SLIBNAME} 137 | ${RM} -f ${HEADERDIR}/qlibcext.h 138 | ${RM} -f ${LIBDIR}/${QLIBCEXT_LIBNAME} 139 | ${RM} -f ${LIBDIR}/${QLIBCEXT_SLIBREALNAME} 140 | ${RM} -f ${LIBDIR}/${QLIBCEXT_SLIBNAME} 141 | 142 | clean: 143 | ${RM} -f ${QLIBC_OBJS} ${QLIBC_LIBNAME} ${QLIBC_SLIBREALNAME} ${QLIBC_SLIBNAME} 144 | ${RM} -f ${QLIBCEXT_OBJS} ${QLIBCEXT_LIBNAME} ${QLIBCEXT_SLIBREALNAME} ${QLIBCEXT_SLIBNAME} 145 | 146 | doc: 147 | doxygen doxygen-qlibc.conf 148 | doxygen doxygen-qlibcext.conf 149 | 150 | cleandoc: 151 | ${RM} -rf ../doc/qlibc 152 | ${RM} -rf ../doc/qlibcext 153 | 154 | ## Compile 155 | .c.o: 156 | ${CC} ${CFLAGS} ${CPPFLAGS} -c -o $@ $< 157 | 158 | -------------------------------------------------------------------------------- /lib/qlibc/src/ipc/qshm.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qLibc - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2010-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: qshm.c 101 2012-05-05 00:13:45Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | /** 32 | * @file qshm.c Shared-memory APIs. 33 | * 34 | * @note 35 | * @code 36 | * [your header file] 37 | * struct SharedData { 38 | * (... structrue definitions ...) 39 | * } 40 | * 41 | * [shared memory creater] 42 | * // create shared memory 43 | * int shmid = qshm_init("/some/file/for/generating/unique/key", 's', sizeof(struct SharedData), true); 44 | * if(shmid < 0) { 45 | * printf("ERROR: Can't initialize shared memory.\n"); 46 | * return -1; 47 | * } 48 | * 49 | * // get shared memory pointer 50 | * struct SharedData *sdata = (SharedData *)qshm_get(shmid); 51 | * if(sdata == NULL) { 52 | * printf("ERROR: Can't get shared memory.\n"); 53 | * return -1; 54 | * } 55 | * 56 | * [shared memory user] 57 | * // get shared memory id 58 | * int shmid = qshm_getid("/some/file/for/generating/unique/key", 's'); 59 | * if(shmid < 0) { 60 | * printf("ERROR: Can't get shared memory id.\n"); 61 | * return -1; 62 | * } 63 | * 64 | * // get shared memory pointer 65 | * struct SharedData *sdata = (SharedData *)qshm_get(shmid); 66 | * if(sdata == NULL) { 67 | * printf("ERROR: Can't get shared memory.\n"); 68 | * return -1; 69 | * } 70 | * @endcode 71 | */ 72 | 73 | #ifndef DISABLE_IPC 74 | 75 | #include 76 | #include 77 | #include 78 | #include 79 | #include 80 | #include "qlibc.h" 81 | #include "qinternal.h" 82 | 83 | /** 84 | * Initialize shared-memory 85 | * 86 | * @param keyfile seed for generating unique IPC key 87 | * @param keyid seed for generating unique IPC key 88 | * @param size size of shared memory 89 | * @param recreate set to true to re-create shared-memory if already exists 90 | * 91 | * @return non-negative shared memory identifier if successful, otherwise returns -1 92 | */ 93 | int qshm_init(const char *keyfile, int keyid, size_t size, bool recreate) 94 | { 95 | key_t semkey; 96 | int shmid; 97 | 98 | /* generate unique key using ftok() */ 99 | if (keyfile != NULL) { 100 | semkey = ftok(keyfile, keyid); 101 | if (semkey == -1) return -1; 102 | } else { 103 | semkey = IPC_PRIVATE; 104 | } 105 | 106 | /* create shared memory */ 107 | if ((shmid = shmget(semkey, size, IPC_CREAT | IPC_EXCL | 0666)) == -1) { 108 | if (recreate == false) return -1; 109 | 110 | /* destroy & re-create */ 111 | if ((shmid = qshm_getid(keyfile, keyid)) >= 0) qshm_free(shmid); 112 | if ((shmid = shmget(semkey, size, IPC_CREAT | IPC_EXCL | 0666)) == -1) return -1; 113 | } 114 | 115 | return shmid; 116 | } 117 | 118 | /** 119 | * Get shared memory identifier by keyfile and keyid for existing shared memory 120 | * 121 | * @param keyfile seed for generating unique IPC key 122 | * @param keyid seed for generating unique IPC key 123 | * 124 | * @return non-negative shared memory identifier if successful, otherwise returns -1 125 | */ 126 | int qshm_getid(const char *keyfile, int keyid) 127 | { 128 | int shmid; 129 | 130 | /* generate unique key using ftok() */ 131 | key_t semkey = ftok(keyfile, keyid); 132 | if (semkey == -1) return -1; 133 | 134 | /* get current shared memory id */ 135 | if ((shmid = shmget(semkey, 0, 0)) == -1) return -1; 136 | 137 | return shmid; 138 | } 139 | 140 | /** 141 | * Get a pointer of shared memory 142 | * 143 | * @param shmid shared memory identifier 144 | * 145 | * @return a pointer of shared memory 146 | */ 147 | void *qshm_get(int shmid) 148 | { 149 | void *pShm; 150 | 151 | if (shmid < 0) return NULL; 152 | pShm = shmat(shmid, 0, 0); 153 | if (pShm == (void *)-1) return NULL; 154 | return pShm; 155 | } 156 | 157 | /** 158 | * De-allocate shared memory 159 | * 160 | * @param shmid shared memory identifier 161 | * 162 | * @return true if successful, otherwise returns false 163 | */ 164 | bool qshm_free(int shmid) 165 | { 166 | if (shmid < 0) return false; 167 | if (shmctl(shmid, IPC_RMID, 0) != 0) return false; 168 | return true; 169 | } 170 | 171 | #endif /* DISABLE_IPC */ 172 | -------------------------------------------------------------------------------- /lib/qlibc/src/internal/doxygen_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /src/hook.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qHttpd - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2008-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: hook.c 214 2012-05-05 00:33:31Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #ifdef ENABLE_HOOK 32 | 33 | #include "qhttpd.h" 34 | 35 | /* EXAMPLE: hash table for doing virtual host 36 | Q_HASHTBL* g_vhostsTbl = NULL; 37 | */ 38 | 39 | bool hookBeforeMainInit(void) 40 | { 41 | 42 | /* 43 | // EXAMPLE: how to change program name to yours 44 | g_prginfo = "YOUR_PROGRAM_INFO" 45 | g_prgname = "YOUR_PROGRAM_NAME"; 46 | g_prgversion = "YOUR_PROGRAM_VERSION"; 47 | */ 48 | 49 | return true; 50 | } 51 | 52 | bool hookAfterConfigLoaded(struct ServerConfig *config, bool bConfigLoadSucceed) 53 | { 54 | 55 | /* EXAMPLE: how to override configurations 56 | config->nPort = 8080; 57 | */ 58 | 59 | /* EXAMPLE: how to load virtual hosts into table 60 | Q_HASHTBL *vhostsTbl = qHashtbl(1000, true, 0); 61 | vhostsTbl->putstr(vhostsTbl, "www.qdecoder.org", "/data/qdecoder"); 62 | vhostsTbl->putstr(vhostsTbl, "www.test.com", "/data/test"); 63 | */ 64 | 65 | return true; 66 | } 67 | 68 | bool hookAfterDaemonInit(void) 69 | { 70 | return true; 71 | } 72 | 73 | // return : number of jobs did, in case of error return -1 74 | int hookWhileDaemonIdle(void) 75 | { 76 | return 0; 77 | } 78 | 79 | bool hookBeforeDaemonEnd(void) 80 | { 81 | return true; 82 | } 83 | 84 | bool hookAfterDaemonSIGHUP(void) 85 | { 86 | return true; 87 | } 88 | 89 | // 90 | // for each connection 91 | // 92 | 93 | bool hookAfterChildInit(void) 94 | { 95 | return true; 96 | } 97 | 98 | bool hookBeforeChildEnd(void) 99 | { 100 | return true; 101 | } 102 | 103 | bool hookAfterConnEstablished(int nSockFd) 104 | { 105 | return true; 106 | } 107 | 108 | // 109 | // request & response hooking 110 | // 111 | // 1. parse request. 112 | // 2. call luaRequestHandler(), if LUA is enabled 113 | // 3. call hookRequestHandler(), if HOOK is enabled. (hook.c) 114 | // 4. call default request handler 115 | // 5. call hookResponseHandler(), if HOOK is enabled. (hook.c) 116 | // 6. call luaResponseHandler(), if LUA is enabled 117 | // 7. response out 118 | 119 | // return response code if you set response then step 4 will be skipped 120 | // otherwise return 0 to bypass then step 4 will handle the request. 121 | int hookRequestHandler(struct HttpRequest *pReq, struct HttpResponse *pRes) 122 | { 123 | return 0; 124 | 125 | /* EXAMPLE: how to add or override methods 126 | int nResCode = 0; 127 | if(!strcmp(pReq->pszRequestMethod, "METHOD_NAME_TO_ADD_OR_REPLACE")) { 128 | nResCode = YOUR_METHOD_CALL(req, res); 129 | } 130 | 131 | return nResCode; 132 | */ 133 | 134 | /* EXAMPLE: how to change document root dynamically 135 | if(pReq->pszDocRoot != NULL) free(pReq->pszDocRoot); 136 | pReq->pszDocRoot = strdup("/NEW_DOCUMENT_ROOT"); 137 | return 0; // pass to default method handler 138 | */ 139 | 140 | /* EXAMPLE: how to map virtual hosted document root 141 | int nResCode = 0; 142 | char *pVirtualDocRoot = g_vhostsTbl->getstr(g_vhostsTbl, pReq->pszRequestDomain, true); 143 | if(pVirtualDocRoot != NULL) { 144 | if(pReq->pszDocumentRoot != NULL) free(pReq->pszDocumentRoot); 145 | pReq->pszDocumentRoot = pVirtualDocRoot; 146 | DEBUG("Virtual Root: %s", pVirtualDocRoot); 147 | } else { 148 | // otherwise deny service 149 | nResCode = response404(pReq, pRes); 150 | } 151 | 152 | return nResCode; 153 | */ 154 | 155 | /* EXAMPLE: HTTP basic authentication 156 | int nResCode = 0; 157 | if(!strcmp(pReq->pszRequestMethod, "PUT")) { 158 | // parse authorization header 159 | struct HttpUser *pHttpUser = httpAuthParse(pReq); 160 | 161 | // validate authorization header 162 | bool bAuth = false; 163 | if(pHttpUser != NULL) { 164 | DEBUG("User %s, Password %s", pHttpUser->szUser, pHttpUser->szPassword); 165 | if(YOUR_PASSWORD_CHECK(pHttpUser) == true) { 166 | bAuth = true; 167 | } 168 | } 169 | 170 | // if authentication failed, send 401 171 | if(bAuth == false) { 172 | // add Basic or Digest Authentication HTTP header 173 | httpResponseSetAuthRequired(pRes, HTTP_AUTH_BASIC, "YOUR_REALM"); 174 | //httpResponseSetAuthRequired(pRes, HTTP_AUTH_DIGEST, pReq->pszRequestDomain); 175 | 176 | // set response 177 | nResCode = httpResponseSetSimple(pReq, pRes, HTTP_CODE_UNAUTHORIZED, true, httpResponseGetMsg(HTTP_CODE_UNAUTHORIZED)); 178 | } 179 | } 180 | return nResCode; 181 | */ 182 | } 183 | 184 | bool hookResponseHandler(struct HttpRequest *pReq, struct HttpResponse *pRes) 185 | { 186 | if (pRes->bOut == true) return true; 187 | 188 | // returns false if you want to log out failure during this call. 189 | return true; 190 | } 191 | 192 | #endif 193 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## qHttpd - http://www.qdecoder.org 3 | ## 4 | ## Copyright (c) 2008-2012 Seungyoung Kim. 5 | ## All rights reserved. 6 | ## 7 | ## Redistribution and use in source and binary forms, with or without 8 | ## modification, are permitted provided that the following conditions are met: 9 | ## 10 | ## 1. Redistributions of source code must retain the above copyright notice, 11 | ## this list of conditions and the following disclaimer. 12 | ## 2. Redistributions in binary form must reproduce the above copyright notice, 13 | ## this list of conditions and the following disclaimer in the documentation 14 | ## and/or other materials provided with the distribution. 15 | ## 16 | ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | ## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | ## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ## ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | ## LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | ## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | ## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | ## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | ## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | ## POSSIBILITY OF SUCH DAMAGE. 27 | ################################################################################ 28 | ## $Id: configure.ac 214 2012-05-05 00:33:31Z seungyoung.kim $ 29 | ################################################################################ 30 | 31 | AC_COPYRIGHT([ 32 | ============================================================================= 33 | qHttpd - http://www.qdecoder.org 34 | 35 | Copyright (c) 2008-2012 Seungyoung Kim. 36 | All rights reserved. 37 | 38 | Redistribution and use in source and binary forms, with or without 39 | modification, are permitted provided that the following conditions are met: 40 | 41 | 1. Redistributions of source code must retain the above copyright notice, 42 | this list of conditions and the following disclaimer. 43 | 2. Redistributions in binary form must reproduce the above copyright notice, 44 | this list of conditions and the following disclaimer in the documentation 45 | and/or other materials provided with the distribution. 46 | 47 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 48 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 51 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 52 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 53 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 54 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 55 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 56 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 57 | POSSIBILITY OF SUCH DAMAGE. 58 | ============================================================================= 59 | ]) 60 | 61 | ## Internal functions 62 | AC_DEFUN([Q_ARG_ENABLE], [ 63 | AC_ARG_ENABLE([$1],[AS_HELP_STRING([--enable-$1], [$2])],,[enableval=no]) 64 | if test "$enableval" = yes; then 65 | AC_MSG_NOTICE(['$1' feature is enabled]) 66 | CPPFLAGS="$CPPFLAGS $3" 67 | OPT_OBJS="$OPT_OBJS $4" 68 | fi 69 | ]) 70 | 71 | AC_DEFUN([Q_ARG_DISABLE], [ 72 | AC_ARG_ENABLE([$1],[AS_HELP_STRING([--disable-$1], [$2])],,[enableval=yes]) 73 | if test "$enableval" = no; then 74 | AC_MSG_NOTICE(['$1' feature is disabled]) 75 | CPPFLAGS="$CPPFLAGS $3" 76 | fi 77 | ]) 78 | 79 | ## Initialize 80 | AC_INIT([qHttpd], [1 RELEASE], [http://www.qdecoder.org/]) 81 | AC_CONFIG_SRCDIR([config.h.in]) 82 | AC_CONFIG_HEADER([config.h]) 83 | AC_CONFIG_FILES([Makefile lib/Makefile src/Makefile]) 84 | 85 | ## Set path 86 | PATH="$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" 87 | CPPFLAGS="$CPPFLAGS -I./ -I/usr/include -I/usr/local/include" 88 | CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" 89 | CPPFLAGS="$CPPFLAGS -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" 90 | LDFLAGS="$LDFLAGS -L/usr/lib -L/usr/local/lib" 91 | 92 | ## Set autoconf setting 93 | #AC_CANONICAL_TARGET 94 | AC_PREFIX_DEFAULT([/usr/local/qhttpd]) 95 | #AC_PRESERVE_HELP_ORDER 96 | 97 | ## Checks for programs. 98 | AC_PROG_CC 99 | if test $ac_compiler_gnu = yes; then 100 | CFLAGS="-Wall" 101 | #else 102 | # AC_MSG_FAILURE([GCC is required.]) 103 | fi 104 | AC_PROG_CC_C99 105 | if test $ac_cv_prog_cc_c99 = no; then 106 | AC_MSG_FAILURE([Compiler does not support C99 mode.]) 107 | fi 108 | 109 | AC_PROG_INSTALL 110 | AC_PROG_MAKE_SET 111 | AC_PATH_PROG(RM, rm) 112 | 113 | ## Checks for header files. 114 | AC_HEADER_STDC 115 | AC_HEADER_STDBOOL 116 | AC_HEADER_STAT 117 | AC_HEADER_DIRENT 118 | AC_CHECK_HEADER([inttypes.h]) 119 | 120 | ## Checks for typedefs, structures, and compiler characteristics. 121 | AC_TYPE_INT8_T 122 | AC_TYPE_INT16_T 123 | AC_TYPE_INT32_T 124 | AC_TYPE_INT64_T 125 | AC_TYPE_UINT8_T 126 | AC_TYPE_UINT16_T 127 | AC_TYPE_UINT32_T 128 | AC_TYPE_UINT64_T 129 | AC_TYPE_SIZE_T 130 | AC_TYPE_SSIZE_T 131 | AC_TYPE_OFF_T 132 | 133 | ## Checks for library functions. 134 | #AC_CHECK_FUNCS([socket sendfile]) 135 | 136 | ## Set additional arguments 137 | OPT_OBJS="" 138 | 139 | Q_ARG_ENABLE([lua], [enable LUA script engine], [-DENABLE_LUA], [luascript.o]) 140 | if test "$enableval" = yes; then 141 | AC_CHECK_HEADER([lua.h], [], AC_MSG_ERROR([Lua library 5.1.4 or above must be installed.])) 142 | AC_CHECK_LIB([lua], [main], [], AC_MSG_ERROR([Lua library 5.1.4 or above must be installed to enable Lua Script feature.])) 143 | AC_CHECK_LIB([dl], [main]) 144 | AC_CHECK_LIB([m], [main]) 145 | fi 146 | 147 | Q_ARG_ENABLE([hook], [enable hook support - compile with hook.c], [-DENABLE_HOOK], [hook.o]) 148 | 149 | Q_ARG_DISABLE([debug], [disable debug build - take off all debugging codes]) 150 | if test "$enableval" = yes; then 151 | CFLAGS="$CFLAGS -g" 152 | CPPFLAGS="$CPPFLAGS -DENABLE_DEBUG" 153 | fi 154 | 155 | ## Print out setting 156 | AC_MSG_NOTICE([CFLAGS $CFLAGS]) 157 | AC_MSG_NOTICE([CPPFLAGS $CPPFLAGS]) 158 | AC_MSG_NOTICE([LDFLAGS $LDFLAGS]) 159 | AC_MSG_NOTICE([LIBS $LIBS $OPT_OBJS]) 160 | 161 | ## Create Makefile 162 | AC_SUBST([OPT_OBJS], [$OPT_OBJS] ) 163 | AC_OUTPUT 164 | -------------------------------------------------------------------------------- /lib/qlibc/examples/listtbl.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qLibc - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2010-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: listtbl.c 86 2012-04-14 07:05:28Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "qlibc.h" 36 | 37 | int main(void) 38 | { 39 | // create a list-table. 40 | qlisttbl_t *tbl = qlisttbl(); 41 | qdlnobj_t obj; 42 | int i; 43 | 44 | // 45 | // TEST 1 : adding elements. 46 | // 47 | 48 | // insert elements (key duplication allowed) 49 | tbl->put(tbl, "e1", "object1", strlen("object1")+1, false); 50 | tbl->putstr(tbl, "e2", "object2", false); 51 | tbl->putstr(tbl, "e3", "object3", false); 52 | tbl->putstr(tbl, "e4", "object4", false); 53 | tbl->putint(tbl, "e5", 5, false); 54 | 55 | // print out 56 | printf("--[Test 1 : adding elements]--\n"); 57 | tbl->debug(tbl, stdout); 58 | 59 | // 60 | // TEST 2 : many ways to find key. 61 | // 62 | 63 | printf("\n--[Test 2 : many ways to find key]--\n"); 64 | printf("get('e2') : %s\n", (char *)tbl->get(tbl, "e2", NULL, false)); 65 | printf("getstr('e2') : %s\n", tbl->getstr(tbl, "e2", false)); 66 | 67 | char *e2 = tbl->getstr(tbl, "e2", true); 68 | printf("getstr('e2', newmem) : %s\n", e2); 69 | free(e2); 70 | 71 | // 72 | // TEST 3 : getmulti() - fetch all duplicated 'e2' keys. 73 | // 74 | 75 | printf("\n--[Test 3 : getmulti() - fetch all duplicated 'e2' keys]--\n"); 76 | size_t numobjs = 0; 77 | qobj_t *objs = tbl->getmulti(tbl, "e2", true, &numobjs); 78 | printf("getmulti('e2') : %d objects found.\n", (int)numobjs); 79 | for (i = 0; objs[i].data != NULL; i++) { 80 | printf("getmulti('e2')[%d]=%s (%zu)\n", 81 | i, (char *)objs[i].data, objs[i].size); 82 | } 83 | tbl->freemulti(objs); 84 | 85 | // 86 | // TEST 4 : travesal a particular key 'e2'. 87 | // 88 | 89 | printf("\n--[Test 4 : travesal a particular key 'e2']--\n"); 90 | memset((void *)&obj, 0, sizeof(obj)); // must be cleared before call 91 | tbl->lock(tbl); 92 | while (tbl->getnext(tbl, &obj, "e2", false) == true) { 93 | printf("NAME=%s, DATA=%s, SIZE=%zu\n", 94 | obj.name, (char *)obj.data, obj.size); 95 | } 96 | tbl->unlock(tbl); 97 | 98 | // 99 | // TEST 5 : travesal a list. 100 | // 101 | 102 | printf("\n--[Test 5 : travesal a list]--\n"); 103 | printf("list size : %zu elements\n", tbl->size(tbl)); 104 | memset((void *)&obj, 0, sizeof(obj)); // must be cleared before call 105 | tbl->lock(tbl); 106 | while (tbl->getnext(tbl, &obj, NULL, true) == true) { 107 | printf("NAME=%s, DATA=%s, SIZE=%zu\n", 108 | obj.name, (char *)obj.data, obj.size); 109 | free(obj.name); 110 | free(obj.data); 111 | } 112 | tbl->unlock(tbl); 113 | 114 | // 115 | // TEST 6 : changed put direction then add 'e3' and 'e4' element. 116 | // 117 | tbl->setputdir(tbl, true); 118 | tbl->putstr(tbl, "e3", "object6", false); 119 | tbl->putstr(tbl, "e4", "object7", false); 120 | 121 | // print out 122 | printf("\n--[Test 6 : changed adding direction then" 123 | " add 'e3' and 'e4' element]--\n"); 124 | tbl->debug(tbl, stdout); 125 | 126 | // 127 | // TEST 7 : add element 'e2' with replace option. 128 | // 129 | tbl->putstr(tbl, "e2", "object8", true); 130 | 131 | // print out 132 | printf("\n--[Test 7 : add element 'e2' with replace option]--\n"); 133 | tbl->debug(tbl, stdout); 134 | 135 | // 136 | // TEST 8 : reverse list 137 | // 138 | tbl->reverse(tbl); 139 | 140 | // print out 141 | printf("\n--[Test 8 : reverse]--\n"); 142 | tbl->debug(tbl, stdout); 143 | 144 | // 145 | // TEST 9 : revert put direction then add some more elements. 146 | // 147 | tbl->setputdir(tbl, false); 148 | tbl->putstr(tbl, "e4", "object9", false); 149 | tbl->putstr(tbl, "e5", "object10", false); 150 | tbl->putstr(tbl, "e6", "object11", false); 151 | tbl->putstr(tbl, "e7", "object12", false); 152 | tbl->putstr(tbl, "e4", "object13", false); 153 | tbl->putstr(tbl, "e6", "object14", false); 154 | 155 | // print out 156 | printf("\n--[Test 9 : revert put direction then add some more" 157 | " elements.]--\n"); 158 | tbl->debug(tbl, stdout); 159 | 160 | // 161 | // TEST 10 : turn on setsort() option. 162 | // 163 | tbl->setsort(tbl, true, false); 164 | 165 | // print out 166 | printf("\n--[Test 10 : turn on setsort() option.\n"); 167 | tbl->debug(tbl, stdout); 168 | 169 | // 170 | // TEST 11 : add new elements 'e1', 'e5' and 'e8'. 171 | // 172 | tbl->putstr(tbl, "e1", "object15", false); 173 | tbl->putint(tbl, "e5", 16, false); 174 | tbl->putstr(tbl, "e8", "object17", false); 175 | 176 | // print out 177 | printf("\n--[Test 11 : add new elements 'e1', 'e5' and 'e8'\n"); 178 | tbl->debug(tbl, stdout); 179 | 180 | // free object 181 | tbl->free(tbl); 182 | 183 | return 0; 184 | } 185 | -------------------------------------------------------------------------------- /src/config.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qHttpd - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2008-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: config.c 214 2012-05-05 00:33:31Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include "qhttpd.h" 32 | 33 | #define fetch2Str(e, d, n) do { \ 34 | const char *t = e->getstr(e, n, false); \ 35 | if(t == NULL) { \ 36 | DEBUG("No such key : %s", n); \ 37 | e->free(e); \ 38 | return false; \ 39 | } \ 40 | qstrcpy(d, sizeof(d), t); \ 41 | } while (false) 42 | 43 | 44 | #define fetch2Int(e, d, n) \ 45 | do { \ 46 | const char *t = e->getstr(e, n, false); \ 47 | if(t == NULL) { \ 48 | DEBUG("No such key : %s", n); \ 49 | e->free(e); \ 50 | return false; \ 51 | } \ 52 | d = atoi(t); \ 53 | } while (false) 54 | 55 | #define fetch2Bool(e, d, n) \ 56 | do { \ 57 | const char *t = e->getstr(e, n, false); \ 58 | if(t == NULL) { \ 59 | DEBUG("No such key : %s", n); \ 60 | e->free(e); \ 61 | return false; \ 62 | } \ 63 | d = (!strcasecmp(t, "YES") || !strcasecmp(t, "TRUE") || \ 64 | !strcasecmp(t, "ON")) ? true : false; \ 65 | } while (false) 66 | 67 | /** 68 | * configuration parser 69 | * 70 | * @param pConf ServerConfig structure 71 | * @param pszFilePath file path of egis.conf 72 | * @return true if successful otherwise returns false 73 | */ 74 | bool loadConfig(struct ServerConfig *pConf, char *pszFilePath) 75 | { 76 | if (pszFilePath == NULL || !strcmp(pszFilePath, "")) { 77 | return false; 78 | } 79 | 80 | // parse configuration file 81 | qlisttbl_t *conflist = qconfig_parse_file(NULL, pszFilePath, '=', true); 82 | if (conflist == NULL) { 83 | DEBUG("Can't open file %s", pszFilePath); 84 | return false; 85 | } 86 | 87 | // copy to structure 88 | qstrcpy(pConf->szConfigFile, sizeof(pConf->szConfigFile), pszFilePath); 89 | 90 | fetch2Str(conflist, pConf->szPidFile, "PidFile"); 91 | fetch2Str(conflist, pConf->szMimeFile, "MimeFile"); 92 | 93 | fetch2Int(conflist, pConf->nPort, "Port"); 94 | 95 | fetch2Int(conflist, pConf->nStartServers, "StartServers"); 96 | fetch2Int(conflist, pConf->nMinSpareServers, "MinSpareServers"); 97 | fetch2Int(conflist, pConf->nMaxSpareServers, "MaxSpareServers"); 98 | fetch2Int(conflist, pConf->nMaxIdleSeconds, "MaxIdleSeconds"); 99 | fetch2Int(conflist, pConf->nMaxClients, "MaxClients"); 100 | fetch2Int(conflist, pConf->nMaxRequestsPerChild, "MaxRequestsPerChild"); 101 | 102 | fetch2Bool(conflist, pConf->bEnableKeepAlive, "EnableKeepAlive"); 103 | fetch2Int(conflist, pConf->nMaxKeepAliveRequests, "MaxKeepAliveRequests"); 104 | 105 | fetch2Int(conflist, pConf->nConnectionTimeout, "ConnectionTimeout"); 106 | fetch2Bool(conflist, pConf->bIgnoreOverConnection, "IgnoreOverConnection"); 107 | fetch2Int(conflist, pConf->nResponseExpires, "ResponseExpires"); 108 | 109 | fetch2Str(conflist, pConf->szDocumentRoot, "DocumentRoot"); 110 | 111 | fetch2Str(conflist, pConf->szAllowedMethods, "AllowedMethods"); 112 | 113 | fetch2Str(conflist, pConf->szDirectoryIndex, "DirectoryIndex"); 114 | 115 | fetch2Bool(conflist, pConf->bEnableLua, "EnableLua"); 116 | fetch2Str(conflist, pConf->szLuaScript, "LuaScript"); 117 | 118 | fetch2Bool(conflist, pConf->bEnableStatus, "EnableStatus"); 119 | fetch2Str(conflist, pConf->szStatusUrl, "StatusUrl"); 120 | 121 | fetch2Str(conflist, pConf->szErrorLog, "ErrorLog"); 122 | fetch2Str(conflist, pConf->szAccessLog, "AccessLog"); 123 | fetch2Int(conflist, pConf->nLogRotate, "LogRotate"); 124 | fetch2Int(conflist, pConf->nLogLevel, "LogLevel"); 125 | 126 | // check config 127 | checkConfig(pConf); 128 | 129 | // 130 | // free resources 131 | // 132 | conflist->free(conflist); 133 | 134 | return true; 135 | } 136 | 137 | bool checkConfig(struct ServerConfig *pConf) 138 | { 139 | // allowed methods parsing 140 | qstrupper(pConf->szAllowedMethods); 141 | if (!strcmp(pConf->szAllowedMethods, "ALL")) { 142 | qstrcpy(pConf->szAllowedMethods, sizeof(pConf->szAllowedMethods), 143 | "OPTIONS,HEAD,GET,PUT" 144 | "," 145 | "PROPFIND,PROPPATCH,MKCOL,MOVE,DELETE,LOCK,UNLOCK"); 146 | } 147 | 148 | if (strstr(pConf->szAllowedMethods, "OPTIONS") != NULL) pConf->methods.bOptions = true; 149 | if (strstr(pConf->szAllowedMethods, "HEAD") != NULL) pConf->methods.bHead = true; 150 | if (strstr(pConf->szAllowedMethods, "GET") != NULL) pConf->methods.bGet = true; 151 | if (strstr(pConf->szAllowedMethods, "PUT") != NULL) pConf->methods.bPut = true; 152 | 153 | if (strstr(pConf->szAllowedMethods, "PROPFIND") != NULL) pConf->methods.bPropfind = true; 154 | if (strstr(pConf->szAllowedMethods, "PROPPATCH") != NULL) pConf->methods.bProppatch = true; 155 | if (strstr(pConf->szAllowedMethods, "MKCOL") != NULL) pConf->methods.bMkcol = true; 156 | if (strstr(pConf->szAllowedMethods, "MOVE") != NULL) pConf->methods.bMove = true; 157 | if (strstr(pConf->szAllowedMethods, "DELETE") != NULL) pConf->methods.bDelete = true; 158 | if (strstr(pConf->szAllowedMethods, "LOCK") != NULL) pConf->methods.bLock = true; 159 | if (strstr(pConf->szAllowedMethods, "UNLOCK") != NULL) pConf->methods.bUnlock = true; 160 | 161 | return true; 162 | } 163 | -------------------------------------------------------------------------------- /src/http_main.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qHttpd - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2008-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: http_main.c 219 2012-05-16 21:57:53Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include "qhttpd.h" 32 | 33 | ///////////////////////////////////////////////////////////////////////// 34 | // PUBLIC FUNCTIONS 35 | ///////////////////////////////////////////////////////////////////////// 36 | 37 | int httpMain(int nSockFd) 38 | { 39 | bool bKeepAlive = false; 40 | 41 | do { 42 | ///////////////////////////////////////////////////////// 43 | // Pre-processing Block 44 | ///////////////////////////////////////////////////////// 45 | 46 | // reset keep-alive 47 | bKeepAlive = false; 48 | 49 | ///////////////////////////////////////////////////////// 50 | // Request processing Block 51 | ///////////////////////////////////////////////////////// 52 | 53 | // parse request 54 | struct HttpRequest *pReq = httpRequestParse(nSockFd, g_conf.nConnectionTimeout); 55 | if (pReq == NULL) { 56 | LOG_ERR("Can't parse request."); 57 | break; 58 | } 59 | 60 | // create response 61 | struct HttpResponse *pRes = httpResponseCreate(pReq); 62 | if (pRes == NULL) { 63 | LOG_ERR("Can't create response."); 64 | httpRequestFree(pReq); 65 | break; 66 | } 67 | 68 | if (pReq->nReqStatus >= 0) { // normal request 69 | // set request information 70 | poolSetConnRequest(pReq); 71 | 72 | // call method handler 73 | // 1. parse request. 74 | // 2. call luaRequestHandler(), if LUA is enabled 75 | // 3. call hookRequestHandler(), if HOOK is enabled. 76 | // 4. call default request handler 77 | // 5. call hookResponseHandler(), if HOOK is enabled. 78 | // 6. call luaResponseHandler(), if LUA is enabled 79 | // 7. response out 80 | if (pReq->nReqStatus > 0) { 81 | int nResCode = 0; 82 | 83 | // check if the request is for server status page 84 | nResCode = httpSpecialRequestHandler(pReq, pRes); 85 | 86 | #ifdef ENABLE_LUA 87 | if (nResCode == 0 && g_conf.bEnableLua == true) { // if response does not set 88 | nResCode = luaRequestHandler(pReq, pRes); 89 | } 90 | #endif 91 | #ifdef ENABLE_HOOK 92 | if (nResCode == 0) { // if response does not set 93 | nResCode = hookRequestHandler(pReq, pRes); 94 | } 95 | #endif 96 | if (nResCode == 0) { // if nothing done, call default handler 97 | nResCode = httpRequestHandler(pReq, pRes); 98 | } 99 | 100 | if (nResCode == 0) { // never reach here 101 | nResCode = response500(pRes); 102 | LOG_ERR("An error occured while processing method."); 103 | } 104 | } else { // bad request 105 | httpResponseSetSimple(pRes, HTTP_CODE_BAD_REQUEST, false, "Your browser sent a request that this server could not understand."); 106 | } 107 | 108 | // serialize & stream out 109 | // hook will be handled inside of httpResponseOut(). 110 | // keep-alive header may be adjusted 111 | httpResponseOut(pRes); 112 | 113 | // logging 114 | httpAccessLog(pReq, pRes); 115 | 116 | // check keep-alive 117 | if (httpHeaderHasCasestr(pRes->pHeaders, "Connection", "Keep-Alive") == true) bKeepAlive = true; 118 | } else { // timeout or connection closed 119 | DEBUG("Connection closed or timed out."); 120 | } 121 | 122 | ///////////////////////////////////////////////////////// 123 | // Post-processing Block 124 | ///////////////////////////////////////////////////////// 125 | 126 | // free resources 127 | if (pRes != NULL) httpResponseFree(pRes); 128 | if (pReq != NULL) httpRequestFree(pReq); 129 | } while (bKeepAlive == true); 130 | 131 | return 0; 132 | } 133 | 134 | /* 135 | * @return response code 136 | */ 137 | int httpRequestHandler(struct HttpRequest *pReq, struct HttpResponse *pRes) 138 | { 139 | if (pReq == NULL || pRes == NULL) return 0; 140 | 141 | int nResCode = 0; 142 | 143 | // HTTP methods : OPTIONS,HEAD,GET,PUT 144 | if (!strcmp(pReq->pszRequestMethod, "OPTIONS")) { 145 | nResCode = httpMethodOptions(pReq, pRes); 146 | } else if (!strcmp(pReq->pszRequestMethod, "HEAD")) { 147 | nResCode = httpMethodHead(pReq, pRes); 148 | } else if (!strcmp(pReq->pszRequestMethod, "GET")) { 149 | nResCode = httpMethodGet(pReq, pRes); 150 | } else if (!strcmp(pReq->pszRequestMethod, "PUT")) { 151 | nResCode = httpMethodPut(pReq, pRes); 152 | } 153 | // HTTP extension - WebDAV methods : PROPFIND,PROPPATCH,MKCOL,MOVE,DELETE,LOCK,UNLOCK 154 | else if (!strcmp(pReq->pszRequestMethod, "PROPFIND")) { 155 | nResCode = httpMethodPropfind(pReq, pRes); 156 | } else if (!strcmp(pReq->pszRequestMethod, "PROPPATCH")) { 157 | nResCode = httpMethodProppatch(pReq, pRes); 158 | } else if (!strcmp(pReq->pszRequestMethod, "MKCOL")) { 159 | nResCode = httpMethodMkcol(pReq, pRes); 160 | } else if (!strcmp(pReq->pszRequestMethod, "MOVE")) { 161 | nResCode = httpMethodMove(pReq, pRes); 162 | } else if (!strcmp(pReq->pszRequestMethod, "DELETE")) { 163 | nResCode = httpMethodDelete(pReq, pRes); 164 | } else if (!strcmp(pReq->pszRequestMethod, "LOCK")) { 165 | nResCode = httpMethodLock(pReq, pRes); 166 | } else if (!strcmp(pReq->pszRequestMethod, "UNLOCK")) { 167 | nResCode = httpMethodUnlock(pReq, pRes); 168 | } 169 | // unknown methods 170 | else { 171 | nResCode = httpMethodNotImplemented(pReq, pRes); 172 | } 173 | 174 | return nResCode; 175 | } 176 | 177 | int httpSpecialRequestHandler(struct HttpRequest *pReq, struct HttpResponse *pRes) 178 | { 179 | if (pReq == NULL || pRes == NULL) return 0; 180 | 181 | int nResCode = 0; 182 | 183 | // check if the request is for server status page 184 | if (g_conf.bEnableStatus == true 185 | && !strcmp(pReq->pszRequestMethod, "GET") 186 | && !strcmp(pReq->pszRequestPath, g_conf.szStatusUrl)) { 187 | nResCode = httpStatusResponse(pReq, pRes); 188 | } 189 | 190 | return nResCode; 191 | } 192 | -------------------------------------------------------------------------------- /lib/qlibc/src/utilities/qtime.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qLibc - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2010-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: qtime.c 63 2012-04-06 00:01:19Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | /** 32 | * @file qtime.c Time handling APIs. 33 | */ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include "qlibc.h" 41 | #include "qinternal.h" 42 | 43 | /** 44 | * Get custom formmatted local time string. 45 | * 46 | * @param buf save buffer 47 | * @param size buffer size 48 | * @param utctime 0 for current time, universal time for specific time 49 | * @param format format for strftime() 50 | * 51 | * @return string pointer of buf 52 | * 53 | * @code 54 | * char *timestr = qtime_localtime_strf(0, "%H:%M:%S"); // HH:MM:SS 55 | * free(timestr); 56 | * char *timestr = qtime_localtime_strf(0, "%Y%m%d%H%M%S"); // YYMMDDhhmmss 57 | * free(timestr); 58 | * @endcode 59 | */ 60 | char *qtime_localtime_strf(char *buf, int size, time_t utctime, 61 | const char *format) 62 | { 63 | if (utctime == 0) utctime = time(NULL); 64 | struct tm *localtm = localtime(&utctime); 65 | 66 | if (strftime(buf, size, format, localtm) == 0) { 67 | snprintf(buf, size, "(buffer small)"); 68 | } 69 | 70 | return buf; 71 | } 72 | 73 | /** 74 | * Get local time string formatted like '02-Nov-2007 16:37:39 +0900'. 75 | * 76 | * @param utctime 0 for current time, universal time for specific time 77 | * 78 | * @return mallocked string pointer of time string 79 | * 80 | * @code 81 | * char *timestr; 82 | * timestr = qtime_localtime_str(0); // now 83 | * free(timestr); 84 | * timestr = qtime_localtime_str(time(NULL)); // same as above 85 | * free(timestr); 86 | * timestr = qtime_localtime_str(time(NULL) - 86400)); // 1 day before 87 | * free(timestr); 88 | * @endcode 89 | */ 90 | char *qtime_localtime_str(time_t utctime) 91 | { 92 | int size = sizeof(char) * (CONST_STRLEN("00-Jan-0000 00:00:00 +0000") + 1); 93 | char *timestr = (char *)malloc(size); 94 | qtime_localtime_strf(timestr, size, utctime, "%d-%b-%Y %H:%M:%S %z"); 95 | return timestr; 96 | } 97 | 98 | /** 99 | * Get local time string formatted like '02-Nov-2007 16:37:39 +0900'. 100 | * 101 | * @param utctime 0 for current time, universal time for specific time 102 | * 103 | * @return internal static string pointer of time string 104 | * 105 | * @code 106 | * printf("%s", qtime_localtime_staticstr(0)); // now 107 | * printf("%s", qtime_localtime_staticstr(time(NULL) + 86400)); // 1 day later 108 | * @endcode 109 | */ 110 | const char *qtime_localtime_staticstr(time_t utctime) 111 | { 112 | static char timestr[sizeof(char) 113 | * (CONST_STRLEN("00-Jan-0000 00:00:00 +0000") + 1)]; 114 | qtime_localtime_strf(timestr, 115 | sizeof(timestr), 116 | utctime, 117 | "%d-%b-%Y %H:%M:%S %z"); 118 | return timestr; 119 | } 120 | 121 | /** 122 | * Get custom formmatted GMT time string. 123 | * 124 | * @param buf save buffer 125 | * @param size buffer size 126 | * @param utctime 0 for current time, universal time for specific time 127 | * @param format format for strftime() 128 | * 129 | * @return string pointer of buf 130 | * 131 | * @code 132 | * char timestr[8+1]; 133 | * qtime_gmt_strf(buf, sizeof(buf), 0, "%H:%M:%S"); // HH:MM:SS 134 | * @endcode 135 | */ 136 | char *qtime_gmt_strf(char *buf, int size, time_t utctime, const char *format) 137 | { 138 | if (utctime == 0) utctime = time(NULL); 139 | struct tm *gmtm = gmtime(&utctime); 140 | 141 | strftime(buf, size, format, gmtm); 142 | return buf; 143 | } 144 | 145 | /** 146 | * Get GMT time string formatted like 'Wed, 11-Nov-2007 23:19:25 GMT'. 147 | * 148 | * @param utctime 0 for current time, universal time for specific time 149 | * 150 | * @return malloced string pointer which points GMT time string. 151 | * 152 | * @code 153 | * char *timestr; 154 | * timestr = qtime_gmt_str(0); // now 155 | * free(timestr); 156 | * timestr = qtime_gmt_str(time(NULL)); // same as above 157 | * free(timestr); 158 | * timestr = qtime_gmt_str(time(NULL) - 86400)); // 1 day before 159 | * free(timestr); 160 | * @endcode 161 | */ 162 | char *qtime_gmt_str(time_t utctime) 163 | { 164 | int size = sizeof(char) 165 | * (CONST_STRLEN("Mon, 00 Jan 0000 00:00:00 GMT") + 1); 166 | char *timestr = (char *)malloc(size); 167 | qtime_gmt_strf(timestr, size, utctime, "%a, %d %b %Y %H:%M:%S GMT"); 168 | return timestr; 169 | } 170 | 171 | /** 172 | * Get GMT time string formatted like 'Wed, 11-Nov-2007 23:19:25 GMT'. 173 | * 174 | * @param utctime 0 for current time, universal time for specific time 175 | * 176 | * @return internal static string pointer which points GMT time string. 177 | * 178 | * @code 179 | * printf("%s", qtime_gmt_staticstr(0)); // now 180 | * printf("%s", qtime_gmt_staticstr(time(NULL) + 86400)); // 1 day later 181 | * @endcode 182 | */ 183 | const char *qtime_gmt_staticstr(time_t utctime) 184 | { 185 | static char timestr[sizeof(char) 186 | * (CONST_STRLEN("Mon, 00-Jan-0000 00:00:00 GMT") + 1)]; 187 | qtime_gmt_strf(timestr, 188 | sizeof(timestr), 189 | utctime, 190 | "%a, %d %b %Y %H:%M:%S GMT"); 191 | return timestr; 192 | } 193 | 194 | /** 195 | * This parses GMT/Timezone(+/-) formatted time sting like 196 | * 'Sun, 04 May 2008 18:50:39 GMT', 'Mon, 05 May 2008 03:50:39 +0900' 197 | * and returns as universal time. 198 | * 199 | * @param gmtstr GMT/Timezone(+/-) formatted time string 200 | * 201 | * @return universal time(UTC). in case of conversion error, returns -1. 202 | * 203 | * @code 204 | * time_t t = time(NULL); 205 | * char *s = qtime_parse_gmtstr(t); 206 | * printf("%d\n", t); 207 | * printf("%s\n", s); 208 | * printf("%d\n", qtime_parse_gmtstr(s)); // this must be same as t 209 | * free(s); 210 | * @endcode 211 | */ 212 | time_t qtime_parse_gmtstr(const char *gmtstr) 213 | { 214 | struct tm gmtm; 215 | if (strptime(gmtstr, "%a, %d %b %Y %H:%M:%S", &gmtm) == NULL) return 0; 216 | time_t utc = timegm(&gmtm); 217 | if (utc < 0) return -1; 218 | 219 | // parse timezone 220 | char *p; 221 | if ((p = strstr(gmtstr, "+")) != NULL) { 222 | utc -= ((atoi(p + 1) / 100) * 60 * 60); 223 | if (utc < 0) return -1; 224 | } else if ((p = strstr(gmtstr, "-")) != NULL) { 225 | utc += ((atoi(p + 1) / 100) * 60 * 60); 226 | } 227 | 228 | return utc; 229 | } 230 | -------------------------------------------------------------------------------- /src/http_status.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qHttpd - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2008-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: http_status.c 214 2012-05-05 00:33:31Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include "qhttpd.h" 32 | 33 | int httpStatusResponse(struct HttpRequest *pReq, struct HttpResponse *pRes) 34 | { 35 | if (pReq == NULL || pRes == NULL) return 0; 36 | 37 | qvector_t *obHtml = httpGetStatusHtml(); 38 | if (obHtml == NULL) return response500(pRes); 39 | 40 | // get size 41 | size_t nHtmlSize = obHtml->list->datasize(obHtml->list); 42 | 43 | // set response 44 | httpResponseSetCode(pRes, HTTP_CODE_OK, true); 45 | httpResponseSetContent(pRes, "text/html; charset=\"utf-8\"", NULL, nHtmlSize); 46 | 47 | // print out header 48 | httpResponseOut(pRes); 49 | 50 | // print out contents 51 | streamStackOut(pReq->nSockFd, obHtml, pReq->nTimeout * 1000); 52 | 53 | // free 54 | obHtml->free(obHtml); 55 | 56 | return HTTP_CODE_OK; 57 | } 58 | 59 | qvector_t *httpGetStatusHtml(void) 60 | { 61 | struct SharedData *pShm = NULL; 62 | pShm = poolGetShm(); 63 | if (pShm == NULL) return NULL; 64 | 65 | char *pszVersionStr = getVersion(); 66 | 67 | qvector_t *obHtml = qvector(); 68 | obHtml->addstr(obHtml, "" CRLF); 69 | obHtml->addstr(obHtml, "" CRLF); 70 | obHtml->addstr(obHtml, "" CRLF); 71 | obHtml->addstrf(obHtml," %s/%s Status" CRLF, g_prgname, g_prgversion); 72 | obHtml->addstr(obHtml, " " CRLF); 73 | obHtml->addstr(obHtml, " " CRLF); 76 | obHtml->addstr(obHtml, "" CRLF); 77 | obHtml->addstr(obHtml, "" CRLF); 78 | 79 | obHtml->addstrf(obHtml,"

%s/%s Status

" CRLF, g_prgname, g_prgversion); 80 | obHtml->addstr(obHtml, "
" CRLF); 81 | obHtml->addstrf(obHtml,"
Server Version: %s
" CRLF, pszVersionStr); 82 | obHtml->addstrf(obHtml,"
Current Time: %s" CRLF, qtime_gmt_staticstr(0)); 83 | obHtml->addstrf(obHtml," , Start Time: %s
" CRLF, qtime_gmt_staticstr(pShm->nStartTime)); 84 | obHtml->addstrf(obHtml,"
Total Connections : %d" CRLF, pShm->nTotalConnected); 85 | obHtml->addstrf(obHtml," , Total Requests : %d
" CRLF, pShm->nTotalRequests); 86 | obHtml->addstrf(obHtml," , Total Launched: %d" CRLF, pShm->nTotalLaunched); 87 | obHtml->addstrf(obHtml," , Running Servers: %d" CRLF, pShm->nRunningChilds); 88 | obHtml->addstrf(obHtml," , Working Servers: %d" CRLF, pShm->nWorkingChilds); 89 | obHtml->addstrf(obHtml,"
Start Servers: %d" CRLF, g_conf.nStartServers); 90 | obHtml->addstrf(obHtml," , Min Spare Servers: %d" CRLF, g_conf.nMinSpareServers); 91 | obHtml->addstrf(obHtml," , Max Spare Servers: %d" CRLF, g_conf.nMaxSpareServers); 92 | obHtml->addstrf(obHtml," , Max Clients: %d
" CRLF, g_conf.nMaxClients); 93 | obHtml->addstr(obHtml, "
" CRLF); 94 | 95 | free(pszVersionStr); 96 | 97 | obHtml->addstr(obHtml, "" CRLF); 98 | obHtml->addstr(obHtml, " " CRLF); 99 | obHtml->addstr(obHtml, " " CRLF); 100 | obHtml->addstr(obHtml, " " CRLF); 101 | obHtml->addstr(obHtml, " " CRLF); 102 | obHtml->addstr(obHtml, " " CRLF); 103 | 104 | obHtml->addstr(obHtml, " " CRLF); 105 | obHtml->addstr(obHtml, " " CRLF); 106 | obHtml->addstr(obHtml, " " CRLF); 107 | obHtml->addstr(obHtml, " " CRLF); 108 | obHtml->addstr(obHtml, " " CRLF); 109 | obHtml->addstr(obHtml, " " CRLF); 110 | 111 | obHtml->addstr(obHtml, " " CRLF); 112 | obHtml->addstr(obHtml, " " CRLF); 113 | obHtml->addstr(obHtml, " " CRLF); 114 | obHtml->addstr(obHtml, " " CRLF); 115 | obHtml->addstr(obHtml, " " CRLF); 116 | 117 | obHtml->addstr(obHtml, " " CRLF); 118 | obHtml->addstr(obHtml, " " CRLF); 119 | obHtml->addstr(obHtml, " " CRLF); 120 | obHtml->addstr(obHtml, " " CRLF); 121 | obHtml->addstr(obHtml, " " CRLF); 122 | 123 | int i, j; 124 | for (i = j = 0; i < g_conf.nMaxClients; i++) { 125 | if (pShm->child[i].nPid == 0) continue; 126 | j++; 127 | 128 | char *pszStatus = "-"; 129 | int nConnRuns = 0; 130 | float nReqRuns = 0; 131 | 132 | if (pShm->child[i].conn.bConnected == true) { 133 | if (pShm->child[i].conn.bRun == true) pszStatus = "W"; 134 | else pszStatus = "K"; 135 | } 136 | 137 | if (pShm->child[i].conn.nEndTime >= pShm->child[i].conn.nStartTime) nConnRuns = difftime(pShm->child[i].conn.nEndTime, pShm->child[i].conn.nStartTime); 138 | else if (pShm->child[i].conn.nStartTime > 0) nConnRuns = difftime(time(NULL), pShm->child[i].conn.nStartTime); 139 | 140 | if (pShm->child[i].conn.bRun == true) nReqRuns = getDiffTimeval(NULL, &pShm->child[i].conn.tvReqTime); 141 | else nReqRuns = getDiffTimeval(&pShm->child[i].conn.tvResTime, &pShm->child[i].conn.tvReqTime); 142 | 143 | char szTimeStr[sizeof(char) * (CONST_STRLEN("YYYYMMDDhhmmss")+1)]; 144 | obHtml->addstr(obHtml, " " CRLF); 145 | obHtml->addstrf(obHtml," " CRLF, j); 146 | obHtml->addstrf(obHtml," " CRLF, (unsigned int)pShm->child[i].nPid); 147 | obHtml->addstrf(obHtml," " CRLF, qtime_gmt_strf(szTimeStr, sizeof(szTimeStr), pShm->child[i].nStartTime, "%Y%m%d%H%M%S")); 148 | obHtml->addstrf(obHtml," " CRLF, pShm->child[i].nTotalConnected); 149 | obHtml->addstrf(obHtml," " CRLF, pShm->child[i].nTotalRequests); 150 | 151 | obHtml->addstrf(obHtml," " CRLF, pszStatus); 152 | obHtml->addstrf(obHtml," " CRLF, pShm->child[i].conn.szAddr, pShm->child[i].conn.nPort); 153 | obHtml->addstrf(obHtml," " CRLF, (pShm->child[i].conn.nStartTime > 0) ? qtime_gmt_strf(szTimeStr, sizeof(szTimeStr), pShm->child[i].conn.nStartTime, "%Y%m%d%H%M%S") : " "); 154 | obHtml->addstrf(obHtml," " CRLF, nConnRuns); 155 | obHtml->addstrf(obHtml," " CRLF, pShm->child[i].conn.nTotalRequests); 156 | 157 | obHtml->addstrf(obHtml," " CRLF, pShm->child[i].conn.szReqInfo); 158 | if (pShm->child[i].conn.nResponseCode == 0) obHtml->addstr(obHtml," " CRLF); 159 | else obHtml->addstrf(obHtml," " CRLF, pShm->child[i].conn.nResponseCode); 160 | obHtml->addstrf(obHtml," " CRLF, (pShm->child[i].conn.tvReqTime.tv_sec > 0) ? qtime_gmt_strf(szTimeStr, sizeof(szTimeStr), pShm->child[i].conn.tvReqTime.tv_sec, "%Y%m%d%H%M%S") : " "); 161 | obHtml->addstrf(obHtml," " CRLF, (nReqRuns * 1000)); 162 | obHtml->addstr(obHtml, " " CRLF); 163 | } 164 | obHtml->addstr(obHtml, "
Server InformationCurrent ConnectionRequest Information
SNOPIDStartedConnsReqsStatusClient IPConn TimeRunsReqsRequest InformationResReq TimeRuns
%d%u%s%d%d%s%s:%d%s%ds%d%s  %d%s%.1fms
" CRLF); 165 | 166 | obHtml->addstr(obHtml, "
" CRLF); 167 | obHtml->addstrf(obHtml,"%s v%s, %s" CRLF, g_prgname, g_prgversion, g_prginfo); 168 | obHtml->addstr(obHtml, "" CRLF); 169 | obHtml->addstr(obHtml, "" CRLF); 170 | 171 | return obHtml; 172 | } 173 | -------------------------------------------------------------------------------- /lib/qlibc/configure.ac: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## qLibc - http://www.qdecoder.org 3 | ## 4 | ## Copyright (c) 2010-2012 Seungyoung Kim. 5 | ## All rights reserved. 6 | ## 7 | ## Redistribution and use in source and binary forms, with or without 8 | ## modification, are permitted provided that the following conditions are met: 9 | ## 10 | ## 1. Redistributions of source code must retain the above copyright notice, 11 | ## this list of conditions and the following disclaimer. 12 | ## 2. Redistributions in binary form must reproduce the above copyright notice, 13 | ## this list of conditions and the following disclaimer in the documentation 14 | ## and/or other materials provided with the distribution. 15 | ## 16 | ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | ## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | ## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ## ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | ## LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | ## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | ## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | ## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | ## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | ## POSSIBILITY OF SUCH DAMAGE. 27 | ################################################################################ 28 | ## $Id: configure.ac 89 2012-04-17 00:37:52Z seungyoung.kim $ 29 | ################################################################################ 30 | 31 | AC_COPYRIGHT([ 32 | ============================================================================== 33 | qLibc - http://www.qdecoder.org 34 | 35 | Copyright (c) 2010-2012 Seungyoung Kim. 36 | All rights reserved. 37 | 38 | Redistribution and use in source and binary forms, with or without 39 | modification, are permitted provided that the following conditions are met: 40 | 41 | 1. Redistributions of source code must retain the above copyright notice, 42 | this list of conditions and the following disclaimer. 43 | 2. Redistributions in binary form must reproduce the above copyright notice, 44 | this list of conditions and the following disclaimer in the documentation 45 | and/or other materials provided with the distribution. 46 | 47 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 48 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 51 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 52 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 53 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 54 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 55 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 56 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 57 | POSSIBILITY OF SUCH DAMAGE. 58 | ============================================================================== 59 | ]) 60 | 61 | ## Internal functions 62 | AC_DEFUN([Q_ARG_ENABLE], [ 63 | AC_ARG_ENABLE([$1],[AS_HELP_STRING([--enable-$1], [$2])],,[enableval=no]) 64 | if test "$enableval" = yes; then 65 | AC_MSG_NOTICE(['$1' feature is enabled]) 66 | CPPFLAGS="$CPPFLAGS $3" 67 | fi 68 | ]) 69 | 70 | AC_DEFUN([Q_ARG_DISABLE], [ 71 | AC_ARG_ENABLE([$1],[AS_HELP_STRING([--disable-$1], [$2])],,[enableval=yes]) 72 | if test "$enableval" = no; then 73 | AC_MSG_NOTICE(['$1' feature is disabled]) 74 | CPPFLAGS="$CPPFLAGS $3" 75 | fi 76 | ]) 77 | 78 | ## Initialize 79 | AC_INIT([qLibc], [2 RELEASE], [http://www.qdecoder.org/]) 80 | AC_CONFIG_SRCDIR([config.h.in]) 81 | AC_CONFIG_HEADER([config.h]) 82 | AC_CONFIG_FILES([Makefile src/Makefile examples/Makefile]) 83 | AC_SUBST(BUILD_TARGETS, ["qlibc qlibcext"]) 84 | AC_SUBST(INSTALL_TARGETS, ["install-qlibc install-qlibcext"]) 85 | AC_SUBST(EXAMPLES_TARGETS, ["TARGETS1"]) 86 | AC_SUBST(DEPLIBS, [""]) 87 | 88 | ## Set path 89 | PATH="$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" 90 | CPPFLAGS="$CPPFLAGS -I./ -I./internal -I/usr/include -I/usr/local/include" 91 | CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" 92 | CPPFLAGS="$CPPFLAGS -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" 93 | LDFLAGS="$LDFLAGS -L/usr/lib -L/usr/local/lib" 94 | 95 | ## Set autoconf setting 96 | #AC_CANONICAL_TARGET 97 | AC_PREFIX_DEFAULT([/usr/local]) 98 | #AC_PRESERVE_HELP_ORDER 99 | 100 | ## Checks for programs. 101 | AC_PROG_CC 102 | if test $ac_compiler_gnu = yes; then 103 | CFLAGS="-Wall -fPIC" 104 | #else 105 | # AC_MSG_FAILURE([GCC is required.]) 106 | fi 107 | AC_PROG_CC_C99 108 | if test $ac_cv_prog_cc_c99 = no; then 109 | AC_MSG_FAILURE([Compiler does not support C99 mode.]) 110 | fi 111 | 112 | AC_PROG_INSTALL 113 | AC_PROG_LN_S 114 | AC_PROG_MAKE_SET 115 | AC_PROG_RANLIB 116 | 117 | AC_PATH_PROG(AR, ar) 118 | AC_PATH_PROG(CHMOD, chmod) 119 | AC_PATH_PROG(LD, ld) 120 | AC_PATH_PROG(RM, rm) 121 | 122 | ## Checks for header files. 123 | AC_HEADER_STDC 124 | AC_HEADER_STDBOOL 125 | AC_HEADER_DIRENT 126 | AC_CHECK_HEADER([inttypes.h]) 127 | 128 | ## Checks for typedefs, structures, and compiler characteristics. 129 | AC_TYPE_INT8_T 130 | AC_TYPE_INT16_T 131 | AC_TYPE_INT32_T 132 | AC_TYPE_INT64_T 133 | AC_TYPE_UINT8_T 134 | AC_TYPE_UINT16_T 135 | AC_TYPE_UINT32_T 136 | AC_TYPE_UINT64_T 137 | AC_TYPE_SIZE_T 138 | AC_TYPE_SSIZE_T 139 | AC_TYPE_OFF_T 140 | 141 | ## Checks for libraries. 142 | 143 | ## Checks for library functions. 144 | #AC_CHECK_FUNCS([socket sendfile]) 145 | 146 | ## 147 | ## --enable section 148 | ## 149 | 150 | Q_ARG_ENABLE([threadsafe], [Enable thread-safe feature. When it's enabled, user applications need to link pthread library. (ex: -lpthread)], [-DENABLE_THREADSAFE]) 151 | if test "$enableval" = yes; then 152 | AC_CHECK_LIB([pthread], [main], [], AC_MSG_ERROR([Cannot find pthread library.])) 153 | AC_SUBST(DEPLIBS, ["-lpthread"]) 154 | fi 155 | 156 | Q_ARG_ENABLE([debug], [Enable debugging output. This will print out internal debugging messages to stdout.], [-DBUILD_DEBUG]) 157 | #Q_ARG_ENABLE([lfs], [Enable large file supports.], [-DENABLE_LFS -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64]) 158 | Q_ARG_DISABLE([ipc], [Disable IPC APIs(src/ipc/) in qlibc library.], [-DDISABLE_IPC]) 159 | #Q_ARG_DISABLE([ext], [Disable all extension APIs in src/extensions directory.], [-DDISABLE_QCONFIG -DDISABLE_QLOG -DDISABLE_QHTTPCLIENT -DDISABLE_QDATABASE]) 160 | Q_ARG_DISABLE([ext], [Disable building qlibext extension library.], []) 161 | if test "$enableval" = no; then 162 | AC_SUBST(BUILD_TARGETS, ["qlibc"]) 163 | AC_SUBST(INSTALL_TARGETS, ["install-qlibc"]) 164 | AC_SUBST(EXAMPLES_TARGETS, ["TARGETS2"]) 165 | fi 166 | #Q_ARG_DISABLE([ext-all], [Disable all extension APIs in src/extensions directory.], [-DDISABLE_QCONFIG -DDISABLE_QLOG -DDISABLE_QHTTPCLIENT -DDISABLE_QDATABASE]) 167 | Q_ARG_DISABLE([ext-qconfig], [Disable qconfig extension in qlibext library.], [-DDISABLE_QCONFIG]) 168 | Q_ARG_DISABLE([ext-qlog], [Disable qlog extension in qlibext library.], [-DDISABLE_QLOG]) 169 | Q_ARG_DISABLE([ext-qhttpclient], [Disable qhttpclient extension in qlibext library.], [-DDISABLE_QHTTPCLIENT]) 170 | Q_ARG_DISABLE([ext-qdatabase], [Disable qdatabase extension in qlibext library.], [-DDISABLE_QDATABASE]) 171 | 172 | if test "$enableval" = yes; then 173 | CFLAGS="$CFLAGS -g -O2" 174 | else 175 | CFLAGS="$CFLAGS -g -O2" 176 | fi 177 | 178 | ## 179 | ## --with section 180 | ## 181 | 182 | AC_ARG_WITH([openssl],[AS_HELP_STRING([--with-openssl], [This will enable HTTPS support in qhttpclient extension API. When it's enabled, user applications are needed to be linked with the openssl library. (ex: -lssl)])],[withval=yes],[withval=no]) 183 | if test "$withval" = yes; then 184 | if test "$with_openssl" = yes; then 185 | with_openssl="/usr/include" 186 | fi 187 | 188 | AC_CHECK_FILE([$with_openssl/openssl/ssl.h],[withval=yes],[withval=no]) 189 | if test "$withval" = yes; then 190 | AC_MSG_NOTICE([HTTPS support in qhttpclient API is enabled]) 191 | CPPFLAGS="$CPPFLAGS -DENABLE_OPENSSL -I$with_openssl" 192 | else 193 | AC_MSG_FAILURE([Cannot find '/openssl/ssl.h' header. Use --with-openssl=/PATH/ to specify the directory where 'openssl' directory is located.]) 194 | fi 195 | fi 196 | 197 | AC_ARG_WITH([mysql],[AS_HELP_STRING([--with-mysql], [This will enable MySQL database support in qdb extension API. When it's enabled, user applications need to link mysql client library. (ex: -lmysqlclient)])],[withval=yes],[withval=no]) 198 | if test "$withval" = yes; then 199 | if test "$with_mysql" = yes; then 200 | with_mysql="/usr/include/mysql" 201 | fi 202 | 203 | AC_CHECK_FILE([$with_mysql/mysql.h],[withval=yes],[withval=no]) 204 | if test "$withval" = yes; then 205 | AC_MSG_NOTICE([MySQL support in qdb API is enabled]) 206 | CPPFLAGS="$CPPFLAGS -DENABLE_MYSQL -I$with_mysql" 207 | else 208 | AC_MSG_FAILURE([Cannot find '$with_mysql/mysql.h' header. Use --with-mysql=/PATH/ to specify the directory where 'mysql.h' is located.]) 209 | fi 210 | fi 211 | 212 | AC_MSG_NOTICE([CFLAGS $CFLAGS]) 213 | AC_MSG_NOTICE([CPPFLAGS $CPPFLAGS]) 214 | #AC_MSG_NOTICE([LIBS $LIBS]) 215 | 216 | ## Create Makefile 217 | AC_OUTPUT 218 | -------------------------------------------------------------------------------- /lib/qlibc/src/ipc/qsem.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qLibc - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2010-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: qsem.c 101 2012-05-05 00:13:45Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | /** 32 | * @file qsem.c Semaphore APIs. 33 | * 34 | * @note 35 | * @code 36 | * [daemon main] 37 | * #define MAX_SEMAPHORES (2) 38 | * 39 | * // create semaphores 40 | * int semid = qsem_init("/some/file/for/generating/unique/key", 'q', MAX_SEMAPHORES, true); 41 | * if(semid < 0) { 42 | * printf("ERROR: Can't initialize semaphores.\n"); 43 | * return -1; 44 | * } 45 | * 46 | * // fork childs 47 | * (... child forking codes ...) 48 | * 49 | * // at the end of daemon, free semaphores 50 | * if(semid >= 0) qsem_free(semid); 51 | * 52 | * [forked child] 53 | * // critical section for resource 0 54 | * qsem_enter(semid, 0); 55 | * (... guaranteed as atomic procedure ...) 56 | * qsem_leave(semid, 0); 57 | * 58 | * (... some codes ...) 59 | * 60 | * // critical section for resource 1 61 | * qsem_enter(semid, 1); 62 | * (... guaranteed as atomic procedure ...) 63 | * qsem_leave(semid, 1); 64 | * 65 | * [other program which uses resource 1] 66 | * int semid = qsem_getid("/some/file/for/generating/unique/key", 'q'); 67 | * if(semid < 0) { 68 | * printf("ERROR: Can't get semaphore id.\n"); 69 | * return -1; 70 | * } 71 | * 72 | * // critical section for resource 1 73 | * qsem_enter(semid, 1); 74 | * (... guaranteed as atomic procedure ...) 75 | * qsem_leave(semid, 1); 76 | * 77 | * @endcode 78 | */ 79 | 80 | #ifndef DISABLE_IPC 81 | 82 | #include 83 | #include 84 | #include 85 | #include 86 | #include 87 | #include "qlibc.h" 88 | #include "qinternal.h" 89 | 90 | /** 91 | * Initialize semaphore 92 | * 93 | * @param keyfile seed for generating unique IPC key 94 | * @param keyid seed for generating unique IPC key 95 | * @param nsems number of semaphores to initialize 96 | * @param recreate set to true to re-create semaphore if exists 97 | * 98 | * @return non-negative shared memory identifier if successful, otherwise returns -1 99 | * 100 | * @code 101 | * int semid = qsem_init("/tmp/mydaemon.pid", 'q', 10, true); 102 | * @endcode 103 | */ 104 | int qsem_init(const char *keyfile, int keyid, int nsems, bool recreate) 105 | { 106 | key_t semkey; 107 | int semid; 108 | 109 | // generate unique key using ftok(); 110 | if (keyfile != NULL) { 111 | semkey = ftok(keyfile, keyid); 112 | if (semkey == -1) return -1; 113 | } else { 114 | semkey = IPC_PRIVATE; 115 | } 116 | 117 | // create semaphores 118 | if ((semid = semget(semkey, nsems, IPC_CREAT | IPC_EXCL | 0666)) == -1) { 119 | if (recreate == false) return -1; 120 | 121 | // destroy & re-create 122 | if ((semid = qsem_getid(keyfile, keyid)) >= 0) qsem_free(semid); 123 | if ((semid = semget(semkey, nsems, IPC_CREAT | IPC_EXCL | 0666)) == -1) return -1; 124 | } 125 | 126 | // initializing 127 | int i; 128 | for (i = 0; i < nsems; i++) { 129 | struct sembuf sbuf; 130 | 131 | /* set sbuf */ 132 | sbuf.sem_num = i; 133 | sbuf.sem_op = 1; 134 | sbuf.sem_flg = 0; 135 | 136 | /* initialize */ 137 | if (semop(semid, &sbuf, 1) != 0) { 138 | qsem_free(semid); 139 | return -1; 140 | } 141 | } 142 | 143 | return semid; 144 | } 145 | 146 | 147 | /** 148 | * Get semaphore identifier by keyfile and keyid for the existing semaphore 149 | * 150 | * @param keyfile seed for generating unique IPC key 151 | * @param keyid seed for generating unique IPC key 152 | * 153 | * @return non-negative shared memory identifier if successful, otherwise returns -1 154 | */ 155 | int qsem_getid(const char *keyfile, int keyid) 156 | { 157 | int semid; 158 | 159 | /* generate unique key using ftok() */ 160 | key_t semkey = ftok(keyfile, keyid); 161 | if (semkey == -1) return -1; 162 | 163 | /* get current semaphore id */ 164 | if ((semid = semget(semkey, 0, 0)) == -1) return -1; 165 | 166 | return semid; 167 | } 168 | 169 | /** 170 | * Turn on the flag of semaphore then entering critical section 171 | * 172 | * @param semid semaphore identifier 173 | * @param semno semaphore number 174 | * 175 | * @return true if successful, otherwise returns false 176 | * 177 | * @note If the semaphore is already turned on, this will wait until released 178 | */ 179 | bool qsem_enter(int semid, int semno) 180 | { 181 | struct sembuf sbuf; 182 | 183 | /* set sbuf */ 184 | sbuf.sem_num = semno; 185 | sbuf.sem_op = -1; 186 | sbuf.sem_flg = SEM_UNDO; 187 | 188 | /* lock */ 189 | if (semop(semid, &sbuf, 1) != 0) return false; 190 | return true; 191 | } 192 | 193 | /** 194 | * Try to turn on the flag of semaphore. If it is already turned on, do not wait. 195 | * 196 | * @param semid semaphore identifier 197 | * @param semno semaphore number 198 | * 199 | * @return true if successful, otherwise(already turned on by other) returns false 200 | */ 201 | bool qsem_enter_nowait(int semid, int semno) 202 | { 203 | struct sembuf sbuf; 204 | 205 | /* set sbuf */ 206 | sbuf.sem_num = semno; 207 | sbuf.sem_op = -1; 208 | sbuf.sem_flg = SEM_UNDO | IPC_NOWAIT; 209 | 210 | /* lock */ 211 | if (semop(semid, &sbuf, 1) != 0) return false; 212 | return true; 213 | } 214 | 215 | /** 216 | * Force to turn on the flag of semaphore. 217 | * 218 | * @param semid semaphore identifier 219 | * @param semno semaphore number 220 | * @param maxwaitms maximum waiting micro-seconds to release 221 | * @param forceflag status will be stored, it can be NULL if you don't need this information 222 | * 223 | * @return true if successful, otherwise returns false 224 | * 225 | * @note 226 | * This will wait the semaphore to be released with in maxwaitms. 227 | * If it it released by locker normally with in maxwaitms, forceflag will be set to false. 228 | * But if maximum maxwaitms is exceed and the semaphore is released forcely, forceflag will 229 | * be set to true. 230 | */ 231 | bool qsem_enter_force(int semid, int semno, int maxwaitms, bool *forceflag) 232 | { 233 | int wait; 234 | for (wait = 0; wait < maxwaitms; wait += 10) { 235 | if (qsem_enter_nowait(semid, semno) == true) { 236 | if (forceflag != NULL) *forceflag = false; 237 | return true; 238 | } 239 | usleep(10*1000); // sleep 10ms 240 | } 241 | 242 | DEBUG("force to unlock semaphore %d-%d", semid, semno); 243 | while (true) { 244 | qsem_leave(semid, semno); 245 | if (qsem_enter_nowait(semid, semno) == true) break; 246 | } 247 | 248 | if (forceflag != NULL) *forceflag = true; 249 | return true; 250 | } 251 | 252 | /** 253 | * Turn off the flag of semaphore then leaving critical section 254 | * 255 | * @param semid semaphore identifier 256 | * @param semno semaphore number 257 | * 258 | * @return true if successful, otherwise returns false 259 | */ 260 | bool qsem_leave(int semid, int semno) 261 | { 262 | struct sembuf sbuf; 263 | 264 | /* set sbuf */ 265 | sbuf.sem_num = semno; 266 | sbuf.sem_op = 1; 267 | sbuf.sem_flg = SEM_UNDO; 268 | 269 | /* unlock */ 270 | if (semop(semid, &sbuf, 1) != 0) return false; 271 | return true; 272 | } 273 | 274 | /** 275 | * Get the status of semaphore 276 | * 277 | * @param semid semaphore identifier 278 | * @param semno semaphore number 279 | * 280 | * @return true for the flag on, false for the flag off 281 | */ 282 | bool qsem_check(int semid, int semno) 283 | { 284 | if (semctl(semid, semno, GETVAL, 0) == 0) return true; // locked 285 | return false; // unlocked 286 | } 287 | 288 | /** 289 | * Release semaphore to system 290 | * 291 | * @param semid semaphore identifier 292 | * 293 | * @return true if successful, otherwise returns false 294 | */ 295 | bool qsem_free(int semid) 296 | { 297 | if (semid < 0) return false; 298 | if (semctl(semid, 0, IPC_RMID, 0) != 0) return false; 299 | return true; 300 | } 301 | 302 | #endif /* DISABLE_IPC */ 303 | -------------------------------------------------------------------------------- /src/child.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * qHttpd - http://www.qdecoder.org 3 | * 4 | * Copyright (c) 2008-2012 Seungyoung Kim. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | ****************************************************************************** 28 | * $Id: child.c 214 2012-05-05 00:33:31Z seungyoung.kim $ 29 | ******************************************************************************/ 30 | 31 | #include "qhttpd.h" 32 | 33 | ///////////////////////////////////////////////////////////////////////// 34 | // PRIVATE FUNCTION PROTOTYPES 35 | ///////////////////////////////////////////////////////////////////////// 36 | static void childEnd(int nStatus); 37 | static void childSignalInit(void *func); 38 | static void childSignal(int signo); 39 | static void childSignalHandler(void); 40 | static void setClientSocketOption(int nSockFd); 41 | 42 | ///////////////////////////////////////////////////////////////////////// 43 | // PUBLIC FUNCTIONS 44 | ///////////////////////////////////////////////////////////////////////// 45 | 46 | void childStart(int nSockFd) 47 | { 48 | // init signal 49 | childSignalInit(childSignal); 50 | 51 | // register at pool. 52 | if (poolChildReg() == false) { 53 | LOG_ERR("Can't register myself at the pool."); 54 | childEnd(EXIT_FAILURE); 55 | } 56 | 57 | #ifdef ENABLE_HOOK 58 | if (hookAfterChildInit() == false) { 59 | LOG_ERR("Hook failed."); 60 | childEnd(EXIT_FAILURE); 61 | } 62 | #endif 63 | 64 | #ifdef ENABLE_LUA 65 | if (g_conf.bEnableLua == true) { 66 | if (luaInit(g_conf.szLuaScript) == false) { 67 | LOG_WARN("Can't initialize lua engine."); 68 | } 69 | } 70 | #endif 71 | 72 | // init random 73 | srand((unsigned)(time(NULL) + getpid() + nSockFd)); 74 | 75 | int nIdleCnt = 0; 76 | while (true) { 77 | // 78 | // SECTION: connection waiting 79 | // 80 | 81 | // signal handling 82 | childSignalHandler(); 83 | 84 | // check exit request 85 | if (poolGetExitRequest() == true) { 86 | DEBUG("Caughted exit request."); 87 | break; 88 | } 89 | 90 | // check maximum requests 91 | if (g_conf.nMaxRequestsPerChild > 0 92 | && poolGetChildTotalRequests() >= g_conf.nMaxRequestsPerChild) { 93 | DEBUG("Maximum requests per child are reached. (%d/%d)", poolGetChildTotalRequests(), g_conf.nMaxRequestsPerChild); 94 | break; 95 | } 96 | 97 | // wait connection 98 | int nStatus = qio_wait_readable(nSockFd, 1000); // wait 1 sec 99 | if (nStatus < 0) break; 100 | else if (nStatus == 0) { 101 | // periodic(1 sec) job here 102 | 103 | // idle time check 104 | nIdleCnt++; 105 | if (g_conf.nMaxIdleSeconds > 0 && nIdleCnt > g_conf.nMaxIdleSeconds) { 106 | int nRunningChilds, nIdleChilds; 107 | nRunningChilds = poolGetNumChilds(NULL, &nIdleChilds); 108 | if (nRunningChilds > g_conf.nStartServers && nIdleChilds > g_conf.nMinSpareServers) { 109 | DEBUG("Maximum idle seconds(%d) are reached.", g_conf.nMaxIdleSeconds); 110 | break; 111 | } 112 | } 113 | 114 | continue; 115 | } 116 | 117 | // new connection arrived 118 | nIdleCnt = 0; 119 | 120 | struct sockaddr_in connAddr; // client address information 121 | socklen_t nConnLen = sizeof(connAddr); 122 | int nNewSockFd; 123 | if ((nNewSockFd = accept(nSockFd, (struct sockaddr *)&connAddr, &nConnLen)) == -1) { 124 | // caught by another process 125 | //DEBUG("I'm late..."); 126 | continue; 127 | } 128 | 129 | // 130 | // SECTION: connection established 131 | // 132 | 133 | // connection accepted 134 | DEBUG("Connection established."); 135 | 136 | // set socket option 137 | setClientSocketOption(nNewSockFd); 138 | 139 | #ifdef ENABLE_HOOK 140 | // connection hook 141 | if (hookAfterConnEstablished(nNewSockFd) == true) { 142 | #endif 143 | // register client information 144 | if (poolSetConnInfo(nNewSockFd) == true) { 145 | // launch main logic 146 | httpMain(nNewSockFd); 147 | } 148 | #ifdef ENABLE_HOOK 149 | } else { 150 | LOG_ERR("Hook failed."); 151 | } 152 | #endif 153 | // close connection 154 | closeSocket(nNewSockFd); 155 | 156 | // clear client information 157 | poolClearConnInfo(); 158 | 159 | DEBUG("Closing connection."); 160 | } 161 | 162 | // ending connection 163 | childEnd(EXIT_SUCCESS); 164 | } 165 | 166 | static void childEnd(int nStatus) 167 | { 168 | static bool bAlready = false; 169 | 170 | if (bAlready == true) return; 171 | bAlready = true; 172 | 173 | #ifdef ENABLE_LUA 174 | // release lua 175 | if (g_conf.bEnableLua == true) luaFree(); 176 | #endif 177 | 178 | #ifdef ENABLE_HOOK 179 | // hook 180 | if (hookBeforeChildEnd() == false) { 181 | LOG_ERR("Hook failed."); 182 | } 183 | #endif 184 | 185 | // remove child info 186 | if (poolChildDel(0) == false) { 187 | LOG_WARN("Can't find pid %d from connection list", getpid()); 188 | } 189 | 190 | // quit 191 | LOG_INFO("Child terminated."); 192 | 193 | // close log 194 | if (g_acclog != NULL) { 195 | g_acclog->free(g_acclog); 196 | g_acclog = NULL; 197 | } 198 | if (g_errlog != NULL) { 199 | g_errlog->free(g_errlog); 200 | g_errlog = NULL; 201 | } 202 | 203 | exit(nStatus); 204 | } 205 | 206 | static void childSignalInit(void *func) 207 | { 208 | // init sigaction 209 | struct sigaction sa; 210 | sa.sa_handler = func; 211 | sa.sa_flags = 0; 212 | sigemptyset (&sa.sa_mask); 213 | 214 | // to handle 215 | sigaction(SIGHUP, &sa, NULL); 216 | sigaction(SIGTERM, &sa, NULL); 217 | sigaction(SIGINT, &sa, NULL); 218 | 219 | sigaction(SIGUSR1, &sa, NULL); 220 | sigaction(SIGUSR2, &sa, NULL); 221 | 222 | // to ignore 223 | signal(SIGPIPE, SIG_IGN); 224 | 225 | // reset signal flags; 226 | sigemptyset(&g_sigflags); 227 | } 228 | 229 | static void childSignal(int signo) 230 | { 231 | sigaddset(&g_sigflags, signo); 232 | if (signo == SIGTERM || signo == SIGINT) childSignalHandler(); 233 | } 234 | 235 | static void childSignalHandler(void) 236 | { 237 | if (sigismember(&g_sigflags, SIGHUP)) { 238 | sigdelset(&g_sigflags, SIGHUP); 239 | LOG_INFO("Child : Caughted SIGHUP "); 240 | 241 | if (poolSetExitRequest() == false) childEnd(EXIT_FAILURE); 242 | } else if (sigismember(&g_sigflags, SIGTERM)) { 243 | sigdelset(&g_sigflags, SIGTERM); 244 | LOG_INFO("Child : Caughted SIGTERM"); 245 | 246 | childEnd(EXIT_SUCCESS); 247 | } else if (sigismember(&g_sigflags, SIGINT)) { 248 | sigdelset(&g_sigflags, SIGINT); 249 | LOG_INFO("Child : Caughted SIGINT"); 250 | 251 | childEnd(EXIT_SUCCESS); 252 | } else if (sigismember(&g_sigflags, SIGUSR1)) { 253 | sigdelset(&g_sigflags, SIGUSR1); 254 | LOG_INFO("Child : Caughted SIGUSR1"); 255 | 256 | if (g_loglevel < MAX_LOGLEVEL) g_loglevel++; 257 | LOG_INFO("Increasing log-level to %d.", g_loglevel); 258 | 259 | } else if (sigismember(&g_sigflags, SIGUSR2)) { 260 | sigdelset(&g_sigflags, SIGUSR2); 261 | LOG_INFO("Child : Caughted SIGUSR2"); 262 | 263 | if (g_loglevel > 0) g_loglevel--; 264 | LOG_INFO("Decreasing log-level to %d.", g_loglevel); 265 | } 266 | } 267 | 268 | static void setClientSocketOption(int nSockFd) 269 | { 270 | // linger option 271 | if (SET_TCP_LINGER_TIMEOUT > 0) { 272 | struct linger li; 273 | li.l_onoff = 1; 274 | li.l_linger = SET_TCP_LINGER_TIMEOUT; 275 | if (setsockopt(nSockFd, SOL_SOCKET, SO_LINGER, &li, sizeof(struct linger)) < 0) { 276 | LOG_WARN("Socket option(SO_LINGER) set failed."); 277 | } 278 | } 279 | 280 | // nodelay option 281 | if (SET_TCP_NODELAY > 0) { 282 | int so_tcpnodelay = 1; 283 | if (setsockopt(nSockFd, IPPROTO_TCP, TCP_NODELAY, &so_tcpnodelay, sizeof(so_tcpnodelay)) < 0) { 284 | LOG_WARN("Socket option(TCP_NODELAY) set failed."); 285 | } 286 | } 287 | 288 | // nonblock socket 289 | /* 290 | int nSockFlags = fcntl(nSockFd, F_GETFL, 0); 291 | fcntl(nSockFd, F_SETFL, nSockFlags | O_NONBLOCK); 292 | */ 293 | } 294 | --------------------------------------------------------------------------------