Makefile.am | 6 +- Makefile.in | 6 +- c-icap.conf.in | 58 ++- configure | 6 +- configure.in | 4 +- contrib/get_file.pl | 2 +- filetype.c | 2 +- include/debug.h | 2 +- services/Makefile.am | 2 +- services/Makefile.in | 4 +- services/clamav/srv_clamav.c | 2 +- services/url_filter/Makefile.am | 12 + services/url_filter/Makefile.in | 501 +++++++++++++++++++ services/url_filter/makefile.w32 | 15 + services/url_filter/srv_url_filter.c | 892 ++++++++++++++++++++++++++++++++++ 15 files changed, 1481 insertions(+), 33 deletions(-) diff --git a/Makefile.am b/Makefile.am index 2e86d25..45937b2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -28,7 +28,7 @@ c_icap_SOURCES = aserver.c request.c cfg_param.c \ # libicapapi ...... libicapapi_la_CFLAGS= -Iinclude/ @ZLIB_ADD_FLAG@ -DCI_BUILD_LIB -libicapapi_la_LIBADD = @ZLIB_ADD_LDFLAG@ +libicapapi_la_LIBADD = @ZLIB_ADD_LDFLAG@ @DL_ADD_FLAG@ @THREADS_LDADD@ libicapapi_la_LDFLAGS= -shared -version-info 0:1:0 @@ -71,10 +71,6 @@ install-data-local: if test ! -f $(DESTDIR)$(CONFIGDIR)/c-icap.magic; then $(INSTALL) c-icap.magic $(DESTDIR)$(CONFIGDIR)/c-icap.magic; fi $(mkinstalldirs) $(DESTDIR)$(LOGDIR); $(mkinstalldirs) $(DESTDIR)$(SOCKDIR); - chgrp nobody $(DESTDIR)$(LOGDIR) - chmod 775 $(DESTDIR)$(LOGDIR) - chgrp nobody $(DESTDIR)$(SOCKDIR) - chmod 775 $(DESTDIR)$(SOCKDIR) EXTRA_DIST= RECONF INSTALL.txt include/config-w32.h makefile.w32 c-icap.conf c_icap_dll.mak c-icap.conf.in c-icap.magic c_icap.mak c_icap.def \ contrib/get_file.pl contrib/convert_old_magic.pl \ diff --git a/Makefile.in b/Makefile.in index 8ce6f2a..b6dadf8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -294,7 +294,7 @@ c_icap_SOURCES = aserver.c request.c cfg_param.c \ # libicapapi ...... libicapapi_la_CFLAGS = -Iinclude/ @ZLIB_ADD_FLAG@ -DCI_BUILD_LIB -libicapapi_la_LIBADD = @ZLIB_ADD_LDFLAG@ +libicapapi_la_LIBADD = @ZLIB_ADD_LDFLAG@ @DL_ADD_FLAG@ @THREADS_LDADD@ libicapapi_la_LDFLAGS = -shared -version-info 0:1:0 #c_icap the main server @@ -1306,10 +1306,6 @@ install-data-local: if test ! -f $(DESTDIR)$(CONFIGDIR)/c-icap.magic; then $(INSTALL) c-icap.magic $(DESTDIR)$(CONFIGDIR)/c-icap.magic; fi $(mkinstalldirs) $(DESTDIR)$(LOGDIR); $(mkinstalldirs) $(DESTDIR)$(SOCKDIR); - chgrp nobody $(DESTDIR)$(LOGDIR) - chmod 775 $(DESTDIR)$(LOGDIR) - chgrp nobody $(DESTDIR)$(SOCKDIR) - chmod 775 $(DESTDIR)$(SOCKDIR) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/c-icap.conf.in b/c-icap.conf.in index 2fbe4cc..665f418 100644 --- a/c-icap.conf.in +++ b/c-icap.conf.in @@ -3,7 +3,7 @@ # -PidFile /var/run/c-icap.pid +PidFile /var/run/c-icap/c-icap.pid CommandsSocket /var/run/c-icap/c-icap.ctl Timeout 300 KeepAlive On @@ -19,26 +19,26 @@ MaxRequestsPerChild 0 Port 1344 -User wwwrun +User _c_icap Group nobody #ServerAdmin you@your.address # Not implemented yet #ServerName localhost:1344 # Not implemented yet -TmpDir /var/tmp +TmpDir /var/cache/c-icap MaxMemObject 131072 -ServerLog @prefix@/var/log/server.log -AccessLog @prefix@/var/log/access.log +ServerLog /var/log/c-icap/server.log +AccessLog /var/log/c-icap/access.log #DebugLevel 3 -ModulesDir @prefix@/lib/c_icap +ModulesDir @libdir@/c-icap Module logger sys_logger.so Module perl_handler perl_handler.so -sys_logger.Prefix "C-ICAP:" -sys_logger.Facility local1 +sys_logger.Prefix "C-ICAP" +sys_logger.Facility daemon ##Specify wich logger to use...... #Logger sys_logger @@ -89,7 +89,7 @@ Logger file_logger #AuthMethod basic file_basic -ServicesDir @prefix@/lib/c_icap +ServicesDir @libdir@/c-icap Service echo_module srv_echo.so Service url_check_module srv_url_check.so Service antivirus_module srv_clamav.so @@ -112,7 +112,7 @@ srv_clamav.StartSendPercentDataAfter 2M # The Maximum object to be scanned. srv_clamav.MaxObjectSize 5M #The directory which clamav library will use as temporary. -#srv_clamav.ClamAvTmpDir /var/tmp +#srv_clamav.ClamAvTmpDir /var/cache/c-icap #Sets the maximum number of files in archive.)i Set it to 0 to disable it srv_clamav.ClamAvMaxFilesInArchive 0 #Sets the maximal archived file size. Set it to 0 to disable it. @@ -122,10 +122,46 @@ srv_clamav.ClamAvMaxRecLevel 5 # And here the viralator-like mode. # where to save documents -srv_clamav.VirSaveDir /srv/www/htdocs/downloads/ +srv_clamav.VirSaveDir /var/www/html/downloads/ # from where the documents can be retrieved (you can find the get_file.pl script in contrib dir) srv_clamav.VirHTTPServer "http://fortune/cgi-bin/get_file.pl?usename=%f&remove=1&file=" # The refresh rate.... srv_clamav.VirUpdateTime 15 # For which filetypes the "virelator like mode" will be used. srv_clamav.VirScanFileTypes ARCHIVE EXECUTABLE + +Service url_filter_module srv_url_filter.so + +# Memcached server list for url_filter +url_filter.MemcachedServers "127.0.0.1:11211" + +# host2cat server for url_filter +url_filter.Host2CatServer "127.0.0.1:6666" + +# Database settings +url_filter.DBEngine "sqlite3" +#url_filter.DBHost "localhost" +#url_filter.DBPort "5432" +url_filter.DBName "/var/cache/host2cat/filter.db" +#url_filter.DBUser "username" +#url_filter.DBPass "password" + +url_filter.RedirectUrl "http://www.google.com" + +#url_filter.ClientIPHeader "X-Client-IP" +#url_filter.AuthUserHeader "X-Authenticated-User" +#url_filter.AuthUserPrefix "Local://" +#url_filter.AuthUserEncoded 0 + +# Default policy settings +# Values are: 0 - accept, 1 - reject, 2 - redirect +#url_filter.DBOpenErrorPolicy 1 +#url_filter.DBQueryErrorPolicy 0 +#url_filter.UnknownRolePolicy 1 +#url_filter.MemcachedConnectErrorPolicy 1 +#url_filter.MemcachedMissPolicy 0 +#url_filter.EmptyCategoryPolicy 0 +#url_filter.CategoryNotFoundPolicy 1 + +# Default value - LOG_INFO +#url_filter.SyslogPriority 6 diff --git a/configure b/configure index 00dc733..4791a03 100755 --- a/configure +++ b/configure @@ -719,7 +719,7 @@ MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. -PACKAGE_NAME='c_icap' +PACKAGE_NAME='c-icap' PACKAGE_TARNAME='c_icap' PACKAGE_VERSION='060708rc3' PACKAGE_STRING='c_icap 060708rc3' @@ -2306,7 +2306,7 @@ fi # Define the identity of the package. - PACKAGE='c_icap' + PACKAGE='c-icap' VERSION='060708rc3' @@ -13714,7 +13714,7 @@ else fi -ac_config_files="$ac_config_files Makefile c-icap.conf services/Makefile services/echo/Makefile services/url_check/Makefile services/clamav/Makefile modules/Makefile" +ac_config_files="$ac_config_files Makefile c-icap.conf services/Makefile services/echo/Makefile services/url_check/Makefile services/clamav/Makefile modules/Makefile services/url_filter/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure diff --git a/configure.in b/configure.in index afcaab0..a42c217 100644 --- a/configure.in +++ b/configure.in @@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script. #AC_INIT(c_icap,m4_normalize(m4_include([VERSION.m4]))) -AC_INIT(c_icap,060708rc3) +AC_INIT(c-icap,060708rc3) AC_CONFIG_SRCDIR(aserver.c) AM_MAINTAINER_MODE @@ -417,4 +417,4 @@ AM_CONDITIONAL(ISCYGWIN,[test a"$iscygwin" != a]) AM_CONDITIONAL(USEPERL,[test a"$perlcore" != a]) AM_CONDITIONAL(USECLAMAV,[test a"$clamav" != ano]) -AC_OUTPUT([Makefile c-icap.conf services/Makefile services/echo/Makefile services/url_check/Makefile services/clamav/Makefile modules/Makefile]) +AC_OUTPUT([Makefile c-icap.conf services/Makefile services/echo/Makefile services/url_check/Makefile services/clamav/Makefile modules/Makefile services/url_filter/Makefile]) diff --git a/contrib/get_file.pl b/contrib/get_file.pl index f14d315..9860749 100644 --- a/contrib/get_file.pl +++ b/contrib/get_file.pl @@ -24,7 +24,7 @@ else{ } -$filename="/srv/www/htdocs/downloads/".$args{"file"}; +$filename="/var/www/html/downloads/".$args{"file"}; my(@stat)=stat $filename; binmode(STDOUT); if(open (F,"<$filename")){ diff --git a/filetype.c b/filetype.c index e019b12..a1bb997 100644 --- a/filetype.c +++ b/filetype.c @@ -299,7 +299,7 @@ int ci_magics_db_file_add(struct ci_magics_db *db, char *filename) struct ci_magic_record record; FILE *f; - if ((f = fopen(filename, "r+")) == NULL) { + if ((f = fopen(filename, "r")) == NULL) { ci_debug_printf(1, "Error opening magic file: %s\n", filename); return 0; } diff --git a/include/debug.h b/include/debug.h index 684ace6..ea44f12 100644 --- a/include/debug.h +++ b/include/debug.h @@ -36,7 +36,7 @@ CI_DECLARE_FUNC(void) __ldebug_printf(int i,const char *format, ...); #else extern void (*__log_error)(void *req, const char *format,... ); -#define ci_debug_printf(i, args...) if(i<=CI_DEBUG_LEVEL){ if(__log_error) (*__log_error)(NULL,args); if(CI_DEBUG_STDOUT) printf(args);} +#define ci_debug_printf(i, args...) if(i<=CI_DEBUG_LEVEL){ if(CI_DEBUG_STDOUT) printf(args); if(__log_error) (*__log_error)(NULL,args);} #endif diff --git a/services/Makefile.am b/services/Makefile.am index 8396ed3..2e5dabd 100644 --- a/services/Makefile.am +++ b/services/Makefile.am @@ -3,7 +3,7 @@ #SUBDIRS = @BUILD_SERVICES@ -SUBDIRS=echo url_check +SUBDIRS=echo url_check url_filter if USECLAMAV SUBDIRS += clamav diff --git a/services/Makefile.in b/services/Makefile.in index c7373ea..240a387 100644 --- a/services/Makefile.in +++ b/services/Makefile.in @@ -58,7 +58,7 @@ RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive ETAGS = etags CTAGS = ctags -DIST_SUBDIRS = echo url_check clamav +DIST_SUBDIRS = echo url_check clamav url_filter DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -185,7 +185,7 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -SUBDIRS = echo url_check $(am__append_1) +SUBDIRS = echo url_check url_filter $(am__append_1) all: all-recursive .SUFFIXES: diff --git a/services/clamav/srv_clamav.c b/services/clamav/srv_clamav.c index 0ad512f..4f4fe23 100644 --- a/services/clamav/srv_clamav.c +++ b/services/clamav/srv_clamav.c @@ -144,7 +144,7 @@ static struct ci_conf_entry conf_variables[] = { CI_DECLARE_MOD_DATA ci_service_module_t service = { - "srv_clamav", /*Module name */ + "clamav", /*Module name */ "Clamav/Antivirus service", /*Module short description */ ICAP_RESPMOD | ICAP_REQMOD, /*Service type responce or request modification */ srvclamav_init_service, /*init_service. */ diff --git a/services/url_filter/Makefile.am b/services/url_filter/Makefile.am new file mode 100644 index 0000000..5a7f19a --- /dev/null +++ b/services/url_filter/Makefile.am @@ -0,0 +1,12 @@ + +pkglib_LTLIBRARIES=srv_url_filter.la +INCLUDES = -I$(top_srcdir) + +srv_url_filter_la_LIBADD = @MODULES_LIBADD@ -lmemcache -lopendbx +srv_url_filter_la_CFLAGS= -I../../include/ +srv_url_filter_la_LDFLAGS= -no-undefined -module -avoid-version +srv_url_filter_la_SOURCES = srv_url_filter.c + + + +EXTRA_DIST= makefile.w32 srv_url_filter.def diff --git a/services/url_filter/Makefile.in b/services/url_filter/Makefile.in new file mode 100644 index 0000000..b89fc7d --- /dev/null +++ b/services/url_filter/Makefile.in @@ -0,0 +1,501 @@ +# Makefile.in generated by automake 1.8.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +SOURCES = $(srv_url_filter_la_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +subdir = services/url_filter +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(mkdir_p) +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(pkglibdir)" +pkglibLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(pkglib_LTLIBRARIES) +srv_url_filter_la_DEPENDENCIES = +am_srv_url_filter_la_OBJECTS = srv_url_filter_la-srv_url_filter.lo +srv_url_filter_la_OBJECTS = $(am_srv_url_filter_la_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = \ +@AMDEP_TRUE@ ./$(DEPDIR)/srv_url_filter_la-srv_url_filter.Plo +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(srv_url_filter_la_SOURCES) +DIST_SOURCES = $(srv_url_filter_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DL_ADD_FLAG = @DL_ADD_FLAG@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +ISCYGWIN_FALSE = @ISCYGWIN_FALSE@ +ISCYGWIN_TRUE = @ISCYGWIN_TRUE@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +MODULES_LIBADD = @MODULES_LIBADD@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +THREADS_LDADD = @THREADS_LDADD@ +THREADS_LDFLAGS = @THREADS_LDFLAGS@ +USECLAMAV_FALSE = @USECLAMAV_FALSE@ +USECLAMAV_TRUE = @USECLAMAV_TRUE@ +USEPERL_FALSE = @USEPERL_FALSE@ +USEPERL_TRUE = @USEPERL_TRUE@ +VERSION = @VERSION@ +ZLIB_ADD_FLAG = @ZLIB_ADD_FLAG@ +ZLIB_ADD_LDFLAG = @ZLIB_ADD_LDFLAG@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_AS = @ac_ct_AS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DLLTOOL = @ac_ct_DLLTOOL@ +ac_ct_F77 = @ac_ct_F77@ +ac_ct_OBJDUMP = @ac_ct_OBJDUMP@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +clamavinc = @clamavinc@ +clamavlib = @clamavlib@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +perlccflags = @perlccflags@ +perlcore = @perlcore@ +perlldflags = @perlldflags@ +perllib = @perllib@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +pkglib_LTLIBRARIES = srv_url_filter.la +INCLUDES = -I$(top_srcdir) +srv_url_filter_la_LIBADD = @MODULES_LIBADD@ -lmemcache -lopendbx +srv_url_filter_la_CFLAGS = -I../../include/ -I@prefix@/include +srv_url_filter_la_LDFLAGS = -no-undefined -module -avoid-version -L@prefix@/lib +srv_url_filter_la_SOURCES = srv_url_filter.c +EXTRA_DIST = makefile.w32 srv_url_filter.def +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu services/url_filter/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu services/url_filter/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(pkglibdir)" || $(mkdir_p) "$(DESTDIR)$(pkglibdir)" + @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " $(LIBTOOL) --mode=install $(pkglibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) --mode=install $(pkglibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(pkglibdir)/$$f"; \ + else :; fi; \ + done + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \ + p="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$p'"; \ + $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" = "$$p" && dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +srv_url_filter.la: $(srv_url_filter_la_OBJECTS) $(srv_url_filter_la_DEPENDENCIES) + $(LINK) -rpath $(pkglibdir) $(srv_url_filter_la_LDFLAGS) $(srv_url_filter_la_OBJECTS) $(srv_url_filter_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/srv_url_filter_la-srv_url_filter.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +srv_url_filter_la-srv_url_filter.o: srv_url_filter.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(srv_url_filter_la_CFLAGS) $(CFLAGS) -MT srv_url_filter_la-srv_url_filter.o -MD -MP -MF "$(DEPDIR)/srv_url_filter_la-srv_url_filter.Tpo" -c -o srv_url_filter_la-srv_url_filter.o `test -f 'srv_url_filter.c' || echo '$(srcdir)/'`srv_url_filter.c; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/srv_url_filter_la-srv_url_filter.Tpo" "$(DEPDIR)/srv_url_filter_la-srv_url_filter.Po"; else rm -f "$(DEPDIR)/srv_url_filter_la-srv_url_filter.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='srv_url_filter.c' object='srv_url_filter_la-srv_url_filter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/srv_url_filter_la-srv_url_filter.Po' tmpdepfile='$(DEPDIR)/srv_url_filter_la-srv_url_filter.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(srv_url_filter_la_CFLAGS) $(CFLAGS) -c -o srv_url_filter_la-srv_url_filter.o `test -f 'srv_url_filter.c' || echo '$(srcdir)/'`srv_url_filter.c + +srv_url_filter_la-srv_url_filter.obj: srv_url_filter.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(srv_url_filter_la_CFLAGS) $(CFLAGS) -MT srv_url_filter_la-srv_url_filter.obj -MD -MP -MF "$(DEPDIR)/srv_url_filter_la-srv_url_filter.Tpo" -c -o srv_url_filter_la-srv_url_filter.obj `if test -f 'srv_url_filter.c'; then $(CYGPATH_W) 'srv_url_filter.c'; else $(CYGPATH_W) '$(srcdir)/srv_url_filter.c'; fi`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/srv_url_filter_la-srv_url_filter.Tpo" "$(DEPDIR)/srv_url_filter_la-srv_url_filter.Po"; else rm -f "$(DEPDIR)/srv_url_filter_la-srv_url_filter.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='srv_url_filter.c' object='srv_url_filter_la-srv_url_filter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/srv_url_filter_la-srv_url_filter.Po' tmpdepfile='$(DEPDIR)/srv_url_filter_la-srv_url_filter.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(srv_url_filter_la_CFLAGS) $(CFLAGS) -c -o srv_url_filter_la-srv_url_filter.obj `if test -f 'srv_url_filter.c'; then $(CYGPATH_W) 'srv_url_filter.c'; else $(CYGPATH_W) '$(srcdir)/srv_url_filter.c'; fi` + +srv_url_filter_la-srv_url_filter.lo: srv_url_filter.c +@am__fastdepCC_TRUE@ if $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(srv_url_filter_la_CFLAGS) $(CFLAGS) -MT srv_url_filter_la-srv_url_filter.lo -MD -MP -MF "$(DEPDIR)/srv_url_filter_la-srv_url_filter.Tpo" -c -o srv_url_filter_la-srv_url_filter.lo `test -f 'srv_url_filter.c' || echo '$(srcdir)/'`srv_url_filter.c; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/srv_url_filter_la-srv_url_filter.Tpo" "$(DEPDIR)/srv_url_filter_la-srv_url_filter.Plo"; else rm -f "$(DEPDIR)/srv_url_filter_la-srv_url_filter.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='srv_url_filter.c' object='srv_url_filter_la-srv_url_filter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/srv_url_filter_la-srv_url_filter.Plo' tmpdepfile='$(DEPDIR)/srv_url_filter_la-srv_url_filter.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(srv_url_filter_la_CFLAGS) $(CFLAGS) -c -o srv_url_filter_la-srv_url_filter.lo `test -f 'srv_url_filter.c' || echo '$(srcdir)/'`srv_url_filter.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-pkglibLTLIBRARIES + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-pkglibLTLIBRARIES install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-info-am \ + uninstall-pkglibLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/services/url_filter/makefile.w32 b/services/url_filter/makefile.w32 new file mode 100644 index 0000000..67b87d6 --- /dev/null +++ b/services/url_filter/makefile.w32 @@ -0,0 +1,15 @@ +!include + +all: srv_url_filter.Dll + +.c.obj: + $(cc) /I..\..\include /I..\..\ $(cdebug) $(cflags) $(cvarsdll) -I. -DCI_BUILD_MODULE -DUNICODE $*.c + +srv_url_filter.Dll: srv_url_filter.obj + $(link) $(linkdebug) $(dlllflags) /LIBPATH:..\..\ c_icap.lib -def:srv_url_filter.def -out:$*.Dll $** $(DLL_ENTRY) $(EXTRA_LIBS) + +clean: + del *.obj *.dll *.lib + + + diff --git a/services/url_filter/srv_url_filter.c b/services/url_filter/srv_url_filter.c new file mode 100644 index 0000000..eaca9e9 --- /dev/null +++ b/services/url_filter/srv_url_filter.c @@ -0,0 +1,892 @@ +/* + * Copyright (C) 2004 Christos Tsantilas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "c-icap.h" +#include "service.h" +#include "header.h" +#include "body.h" +#include "simple_api.h" +#include "debug.h" +#include "ci_threads.h" +#include +#include +#undef HAVE_CONFIG_H +#include +#include +#include +#ifndef REG_BASIC +#define REG_BASIC 0 +#endif + +#define CACHETTL 3600 + +struct memcache *mc; + +int url_filter_init_service(ci_service_xdata_t *srv_xdata,struct ci_server_conf *server_conf); +int url_filter_post_init_service(ci_service_xdata_t *srv_xdata,struct ci_server_conf *server_conf); +void url_filter_close_service (ci_service_xdata_t *srv_xdata); +void * url_filter_init_request_data(ci_request_t *req); +void url_filter_release_data(void *data); +int url_filter_process(ci_request_t *); +int url_filter_check_preview(char *preview_data,int preview_data_len,ci_request_t *); +int url_filter_io(char *wbuf,int *wlen,char *rbuf,int *rlen,int iseof,ci_request_t *req); +//int url_filter_write(char *buf,int len ,int iseof,request_t *req); +//int url_filter_read(char *buf,int len,request_t *req); +static unsigned dotip2int (char *str); +static unsigned str2int (const char *str); + +static char *MemcachedServers; +static char *Host2CatServer; +static char *DBEngine; +static char *DBHost; +static char *DBPort; +static char *DBName; +static char *DBUser; +static char *DBPass; +static char *RedirectUrl; +static char *ClientIPHeader = "X-Client-IP"; +static char *AuthUserHeader = "X-Authenticated-User"; +static char *AuthUserPrefix; +static int AuthUserEncoded = 1; +// Values 0 - ACCEPT, 1 - REJECT, 2 - REDIRECT +static int DBOpenErrorPolicy = 1; // SQLite database doesn't opened +static int DBQueryErrorPolicy = 0; // Error executing SQLite query +static int UnknownRolePolicy = 1; // Can't find role for user@ip +static int MemcachedConnectErrorPolicy = 1;// No connection to memcached server(s) +static int MemcachedMissPolicy = 0; // Host category missed at memcached server(s) +static int EmptyCategoryPolicy = 0; // No categories for host +static int CategoryNotFoundPolicy = 1; // Host categories doesn't exists in roles definition +static int SyslogPriority = LOG_INFO; // Priority for syslog() + +static int fd = -1; +static struct sockaddr_in addr; +static odbx_t *dbh; + +static ci_thread_mutex_t mtx; + +static struct ci_conf_entry conf_variables[]={ + {"MemcachedServers",&MemcachedServers,ci_cfg_set_str,NULL}, + {"Host2CatServer",&Host2CatServer,ci_cfg_set_str,NULL}, + {"DBEngine",&DBEngine,ci_cfg_set_str,NULL}, + {"DBHost",&DBHost,ci_cfg_set_str,NULL}, + {"DBPort",&DBPort,ci_cfg_set_str,NULL}, + {"DBName",&DBName,ci_cfg_set_str,NULL}, + {"DBUser",&DBUser,ci_cfg_set_str,NULL}, + {"DBPass",&DBPass,ci_cfg_set_str,NULL}, + {"RedirectUrl",&RedirectUrl,ci_cfg_set_str,NULL}, + {"ClientIPHeader",&ClientIPHeader,ci_cfg_set_str,NULL}, + {"AuthUserHeader",&AuthUserHeader,ci_cfg_set_str,NULL}, + {"AuthUserPrefix",&AuthUserPrefix,ci_cfg_set_str,NULL}, + {"AuthUserEncoded",&AuthUserEncoded,ci_cfg_set_int,NULL}, + {"DBOpenErrorPolicy",&DBOpenErrorPolicy,ci_cfg_set_int,NULL}, + {"DBQueryErrorPolicy",&DBQueryErrorPolicy,ci_cfg_set_int,NULL}, + {"UnknownRolePolicy",&UnknownRolePolicy,ci_cfg_set_int,NULL}, + {"MemcachedConnectErrorPolicy",&MemcachedConnectErrorPolicy,ci_cfg_set_int,NULL}, + {"MemcachedMissPolicy",&MemcachedMissPolicy,ci_cfg_set_int,NULL}, + {"EmptyCategoryPolicy",&EmptyCategoryPolicy,ci_cfg_set_int,NULL}, + {"CategoryNotFoundPolicy",&CategoryNotFoundPolicy,ci_cfg_set_int,NULL}, + {"SyslogPriority",&SyslogPriority,ci_cfg_set_int,NULL}, + {NULL,NULL,NULL,NULL} +}; + + +//service_module echo={ +CI_DECLARE_MOD_DATA ci_service_module_t service={ + "url_filter", + "Url Filter service", + ICAP_REQMOD, + url_filter_init_service, /* init_service*/ + url_filter_post_init_service, /*post_init_service*/ + url_filter_close_service, /*close_Service*/ + url_filter_init_request_data,/* init_request_data*/ + url_filter_release_data, /*Release request data*/ + url_filter_check_preview, + url_filter_process, + url_filter_io, + conf_variables, + NULL +}; + +struct url_filter_data{ + ci_cached_file_t *body; + int denied; +}; + +enum http_methods {HTTP_UNKNOWN=0,HTTP_GET, HTTP_POST}; + +struct http_info{ + int http_major; + int http_minor; + int method; + char site[CI_MAXHOSTNAMELEN+1]; + char page[1024]; /*I think it is enough*/ +// char server_ip [CI_IPLEN + 1]; + char *client_ip; + char auth_user [MAX_USERNAME_LEN + 1]; +}; + + +int url_filter_init_service(ci_service_xdata_t *srv_xdata,struct ci_server_conf *server_conf){ + unsigned int xops; + printf("Initialization of url_filter module......\n"); + ci_service_set_preview(srv_xdata, 0); + xops = CI_XCLIENTIP | CI_XSERVERIP; + xops |= CI_XAUTHENTICATEDUSER | CI_XAUTHENTICATEDGROUPS; + ci_service_set_xopts(srv_xdata, xops); + return CI_OK; +} + +int url_filter_post_init_service (ci_service_xdata_t *srv_xdata,struct ci_server_conf *server_conf) +{ + int nservers, retval; + char *p, *p1, *ep; + + if (!MemcachedServers || !*MemcachedServers) { + ci_debug_printf (1, "Empty MemcachedServers list\n"); + return CI_ERROR; + } + + if (!(mc = mc_new ())) { + ci_debug_printf (1, "No memory for mc structure\n"); + return CI_ERROR; + } + + ep = MemcachedServers + strlen(MemcachedServers); + for (nservers = 0, p = MemcachedServers; p < ep; p = p1 + 1) { + // p points to beginning of server, p1 points to end of server + p1 = strchr (p, ','); + if (!p1) p1 = p + strlen (p); + + if (p1 == p) { + ci_debug_printf (5, "Empty server in '%s' - ignored\n", MemcachedServers); + } else if ((retval = mc_server_add5 (mc, p, p1 - p))) { + ci_debug_printf (5, "server add for server %.*s returns %d\n", (int)(p1 - p), p, retval); + } else { + nservers++; + ci_debug_printf (5, "server %.*s successfully added\n", (int)(p1 - p), p); + } + } + + if (!nservers) { + ci_debug_printf (1, "No servers added\n"); + mc_free (mc); + mc = NULL; + return CI_ERROR; + } + + if (!Host2CatServer || !*Host2CatServer) { + ci_debug_printf (1, "Empty Host2CatServer\n"); + return CI_ERROR; + } + + if (!(p = strchr (Host2CatServer, ':'))) { + ci_debug_printf (1, "No port number in Host2CatServer %s\n", Host2CatServer); + return CI_ERROR; + } + + *p = 0; + bzero (&addr, sizeof addr); + addr.sin_family = AF_INET; + addr.sin_port = htons (atoi (p + 1)); + inet_pton (AF_INET, Host2CatServer, &addr.sin_addr); + *p = ':'; + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd == -1) { + ci_debug_printf (1, "Can't open UDP socket to Host2CatServer: %s\n", strerror (errno)); + return CI_ERROR; + } + + if (!DBEngine || !*DBEngine) { + ci_debug_printf (1, "Empty DBEngine\n"); + return CI_ERROR; + } + + retval = odbx_init (&dbh, DBEngine, DBHost, DBPort); + if (retval != ODBX_ERR_SUCCESS) { + ci_debug_printf (1, "Error initializing DB handle: %s\n", odbx_error (dbh, retval)); + return CI_ERROR; + } + + if (!DBName || !*DBName) { + ci_debug_printf (1, "Empty DBName\n"); + return CI_ERROR; + } + + retval = odbx_bind_simple (dbh, DBName, DBUser, DBPass); + if (retval != ODBX_ERR_SUCCESS) { + ci_debug_printf (1, "Error binding to database: %s\n", odbx_error (dbh, retval)); + odbx_finish (dbh); + dbh = NULL; + return CI_ERROR; + } + + if (!RedirectUrl || !*RedirectUrl) ci_debug_printf (1, "Empty redirect URL\n"); + + if (ci_thread_mutex_init(&mtx)) + return CI_ERROR; + + return CI_OK; +} + + +void url_filter_close_service (ci_service_xdata_t *srv_xdata) +{ + if (mc) { + mc_free (mc); + mc = NULL; + } + if (fd != -1) close (fd); + if (dbh) { + odbx_unbind (dbh); + odbx_finish (dbh); + } + + ci_thread_mutex_destroy(&mtx); +} + +void *url_filter_init_request_data(ci_request_t *req){ + struct url_filter_data *uc=malloc(sizeof(struct url_filter_data)); + uc->body=NULL; + uc->denied = 0; + return uc; /*Get from a pool of pre-allocated structs better......*/ +} + + +void url_filter_release_data(void *data){ + struct url_filter_data *uc=data; + if(uc->body) + ci_cached_file_destroy(uc->body); + free(uc); /*Return object to pool.....*/ +} + + +static int get_http_info(ci_request_t *req,ci_headers_list_t *req_header , struct http_info *httpinf){ + char *str; + int i; + + /*Now get the site name*/ + str=ci_headers_value(req_header,"Host"); + strncpy(httpinf->site,str,CI_MAXHOSTNAMELEN); + httpinf->site[CI_MAXHOSTNAMELEN]='\0'; + + str=req_header->headers[0]; + if(str[0]=='g' || str[0]=='G') /*Get request....*/ + httpinf->method=HTTP_GET; + else if(str[0]=='p' || str[0]=='P') /*post request....*/ + httpinf->method=HTTP_POST; + else{ + httpinf->method=HTTP_UNKNOWN; + return 0; + } + if((str=strchr(str,' '))==NULL){ /*The request must have the form:GETPOST page HTTP/X.X */ + return 0; + } + while(*str==' ') str++; + i=0; + while(*str!=' ' && *str!='\0' && i<1022) /*copy page to the struct.*/ + httpinf->page[i++]=*str++; + httpinf->page[i]='\0'; + + if(*str!=' '){ /*Where is the protocol info?????*/ + return 0; + } + while(*str==' ') str++; + if(*str!='H' || *(str+4)!='/'){ /*Not in HTTP/X.X form*/ + return 0; + } + str+=5; + httpinf->http_major=strtol(str,&str,10); + if(*str!='.'){ + return 0; + } + str++; + httpinf->http_minor=strtol(str,&str,10); + + + return 1; +} + +static int check_destination (struct http_info *httpinf, int policy) +{ + odbx_result_t *sth; + unsigned ip, role = 0, *ncats; + int i, rc = CategoryNotFoundPolicy, retval; + char *cats = NULL, *p, *p1, buf [1024], rname[64], *uname; + char key[64], *val = NULL; + int valsz, found; + + uname = AuthUserPrefix && *AuthUserPrefix && !strncmp (httpinf->auth_user, AuthUserPrefix, strlen (AuthUserPrefix)) ? httpinf->auth_user + strlen (AuthUserPrefix) : httpinf->auth_user; + ip = dotip2int (httpinf->client_ip); + snprintf (key, sizeof key, "%s@%s", uname, httpinf->client_ip); + ci_debug_printf (5, "Uname: %s\n", uname); + ci_debug_printf (5, "IP: %s\n", httpinf->client_ip); + ci_debug_printf (5, "URL: %s\n", httpinf->page); + ci_debug_printf (5, "Host: %s\n", httpinf->site); + + if (!dbh) { + ci_debug_printf (1, "DB handle doesn't opened\n"); + rc = DBOpenErrorPolicy; + goto print_log; + } + + // Find user role + ci_thread_mutex_lock(&mtx); + val = mc_aget(mc, key, strlen(key)); + ci_thread_mutex_unlock(&mtx); + if (val) { + char *ptr; + + ci_debug_printf(5, "Found role in cache\n"); + role = strtol(val, NULL, 10); + ptr = strchr(val, ':') + 1; + strlcpy(rname, ptr, sizeof rname); + free(val); + goto cached_role; + } + + snprintf (buf, sizeof buf, "SELECT u.addr, u.mask, u.rolid, r.rname FROM users u, roles r WHERE u.uname = '%s' AND u.rolid = r.rolid ORDER BY mask DESC", uname); + + ci_thread_mutex_lock(&mtx); + retval = odbx_query (dbh, buf, strlen (buf)); + if (retval != ODBX_ERR_SUCCESS) { + ci_debug_printf (1, "Error executing SQL query '%s': %s\n", buf, odbx_error (dbh, retval)); + rc = DBQueryErrorPolicy; + ci_thread_mutex_unlock(&mtx); + goto print_log; + } + + retval = odbx_result (dbh, &sth, NULL, 0); + ci_thread_mutex_unlock(&mtx); + if (retval < 0) { + ci_debug_printf (1, "Error getting SQL query result '%s': %s\n", buf, odbx_error (dbh, retval)); + rc = DBQueryErrorPolicy; + goto print_log; + } + + while ((retval = odbx_row_fetch (sth)) != 0) { + unsigned net, mask; + if (retval < 0) { + ci_debug_printf (1, "Error fetching result row '%s', :%s\n", buf, odbx_error (dbh, retval)); + break; + } + net = str2int (odbx_field_value (sth, 0)); + mask = str2int (odbx_field_value (sth, 1)); + if ((ip & mask) == net) { + role = str2int (odbx_field_value (sth, 2)); + strlcpy (rname, odbx_field_value (sth, 3), sizeof rname); + break; + } + } + + // Find default role + if (!role) { + odbx_result_free (sth); + snprintf (buf, sizeof buf, "SELECT u.addr, u.mask, u.rolid, r.rname FROM users u, roles r WHERE u.uname = '%s' AND u.rolid = r.rolid ORDER BY mask DESC", ""); + + ci_thread_mutex_lock(&mtx); + retval = odbx_query (dbh, buf, strlen (buf)); + if (retval != ODBX_ERR_SUCCESS) { + ci_debug_printf (1, "Error executing SQL query '%s': %s\n", buf, odbx_error (dbh, retval)); + rc = DBQueryErrorPolicy; + ci_thread_mutex_unlock(&mtx); + goto print_log; + } + + retval = odbx_result (dbh, &sth, NULL, 0); + ci_thread_mutex_unlock(&mtx); + if (retval < 0) { + ci_debug_printf (1, "Error getting SQL query result '%s': %s\n", buf, odbx_error (dbh, retval)); + rc = DBQueryErrorPolicy; + goto print_log; + } + + while ((retval = odbx_row_fetch (sth)) != 0) { + unsigned net, mask; + if (retval < 0) { + ci_debug_printf (1, "Error fetching result row '%s', :%s\n", buf, odbx_error (dbh, retval)); + break; + } + net = str2int (odbx_field_value (sth, 0)); + mask = str2int (odbx_field_value (sth, 1)); + if ((ip & mask) == net) { + role = str2int (odbx_field_value (sth, 2)); + strlcpy (rname, odbx_field_value (sth, 3), sizeof rname); + break; + } + } + } + odbx_result_free (sth); + + if (role) { + snprintf(buf, sizeof buf, "%d:%s", role, rname); + ci_thread_mutex_lock(&mtx); + mc_add(mc, key, strlen(key), buf, strlen(buf) + 1, CACHETTL, 0); + ci_thread_mutex_unlock(&mtx); + } + +cached_role: + ci_debug_printf (5, "Role: %s\n", role ? rname : "UNKNOWN"); + if (!role) { + rc = UnknownRolePolicy; + goto print_log; + } + + // Read URL list + snprintf (key, sizeof key, "url:%s", rname); + ci_thread_mutex_lock(&mtx); + val = mc_aget(mc, key, strlen(key)); + ci_thread_mutex_unlock(&mtx); + if (val) { + char *s; + + ci_debug_printf(5, "Found URL list in cache\n"); + + for (s = val; *s;) { + regex_t preg; + const char *url; + int action; + + action = strtol(s, NULL, 10); + url = strchr(s, ':') + 1; + s = strchr(url, ' '); + *s++ = '\0'; + + ci_debug_printf(9, "checking url %s against list: " + "action %d, regex %s", httpinf->page, action, url); + rc = regcomp(&preg, url, REG_BASIC | REG_ICASE | + REG_NOSUB); + if (rc) { + ci_debug_printf(1, "Error compiling regular " + "expression '%s': %d\n", url, rc); + continue; + } + rc = regexec(&preg, httpinf->page, 0, NULL, 0); + regfree(&preg); + if (!rc) { + free(val); + rc = action; + goto print_log; + } + } + free(val); + goto cached_urls; + } + + snprintf (buf, sizeof buf, "SELECT l.url, l.action FROM lists l, hierarchy h WHERE h.child = %d AND h.parent = l.rolid ORDER BY action DESC, rolid, stars, length (l.url)", role); + + ci_thread_mutex_lock(&mtx); + retval = odbx_query (dbh, buf, strlen (buf)); + if (retval != ODBX_ERR_SUCCESS) { + ci_debug_printf (1, "Error executing SQL query '%s': %s\n", buf, odbx_error (dbh, retval)); + rc = DBQueryErrorPolicy; + ci_thread_mutex_unlock(&mtx); + goto print_log; + } + + retval = odbx_result (dbh, &sth, NULL, 0); + ci_thread_mutex_unlock(&mtx); + if (retval < 0) { + ci_debug_printf (1, "Error getting SQL query result '%s': %s\n", buf, odbx_error (dbh, retval)); + rc = DBQueryErrorPolicy; + goto print_log; + } + + + // Check URL list + val = NULL; + valsz = 1; + found = 0; + while ((retval = odbx_row_fetch (sth)) != 0) { + regex_t preg; + const char *url; + int action; + + if (retval < 0) { + ci_debug_printf (1, "Error fetching result row '%s': %s\n", buf, odbx_error (dbh, retval)); + break; + } + + if (val != (void *)-1) { + char *ptr; + int len; + + len = strlen(odbx_field_value(sth, 0)) + + strlen(odbx_field_value(sth, 1)) + 2; + if ((ptr = realloc(val, valsz + len)) == NULL) { + free(val); + val = (void *)-1; + } else { + val = ptr; + asprintf(&ptr, "%s:%s ", + odbx_field_value(sth, 1), + odbx_field_value(sth, 0)); + if (ptr == NULL) { + free(val); + val = (void *)-1; + } else { + strcat(val, ptr); + valsz += len; + } + } + } + + url = odbx_field_value (sth, 0); + action = str2int (odbx_field_value (sth, 1)); + ci_debug_printf (9, "checking url %s against list: action %d, regex %s", httpinf->page, action, url); + rc = regcomp (&preg, url, REG_BASIC | REG_ICASE | REG_NOSUB); + if (rc) { + ci_debug_printf (1, "Error compiling regular expression '%s': %d\n", url, rc); + continue; + } + rc = regexec (&preg, httpinf->page, 0, NULL, 0); + regfree (&preg); + if (!rc && !found) { + found = 1; + rc = action; + } + } + odbx_result_free (sth); + + if (val && val != (void *)-1) { + ci_thread_mutex_lock(&mtx); + mc_add(mc, key, strlen(key), val, strlen(val) + 1, + CACHETTL, 0); + ci_thread_mutex_unlock(&mtx); + free(val); + } + + if (found) + goto print_log; + +cached_urls: + // Get host category + if (!mc) { + rc = MemcachedConnectErrorPolicy; + goto print_log; + } + ci_thread_mutex_lock(&mtx); + cats = mc_aget (mc, (char *) httpinf->site, strlen (httpinf->site)); + ci_thread_mutex_unlock(&mtx); + ci_debug_printf (5, "Cats: %s\n", cats ? cats : "MISSED"); + if (!cats) { + if (fd != -1) sendto (fd, httpinf->site, strlen (httpinf->site) + 1, 0, (struct sockaddr *)&addr, sizeof addr); + rc = MemcachedMissPolicy; + goto print_log; + } + if (!*cats) { + rc = EmptyCategoryPolicy; + goto print_log; + } + + // Convert cats to array of unsigned + for (i = 1, p = strchr (cats, ':'); p; p = strchr (p + 1, ':'), i++) + ; + ncats = calloc (i + 1, sizeof (unsigned)); + for (i = 0, p = cats, p1 = strchr (p, ':'); *p; p1 = strchr (p, ':'), i++) { + if (p1) *p1 = 0; + ncats [i] = str2int (p); + if (p1) { + *p1 = ':'; + p = p1 + 1; + } else + p += strlen (p); + } + ncats [i] = 0; + + // Read category list + snprintf(key, sizeof key, "cat:%d", role); + ci_thread_mutex_lock(&mtx); + val = mc_aget(mc, key, strlen(key)); + ci_thread_mutex_unlock(&mtx); + if (val) { + char *s; + + ci_debug_printf(5, "Found category list in cache\n"); + + for (s = val; *s;) { + char *catstr; + int cat, action; + unsigned *u; + + action = strtol(s, NULL, 10); + catstr = strchr(s, ':') + 1; + s = strchr(catstr, ' '); + *s++ = '\0'; + + cat = str2int(catstr); + for (u = ncats; *u; u++) { + ci_debug_printf(9, "checking host category %d " + "against REJECT and REDIRECT category %d\n", + *u, cat); + if (cat == *u) { + free(val); + rc = action; + goto print_log; + } + } + } + + free(val); + goto print_log; + } + + snprintf (buf, sizeof buf, "SELECT p.cat, p.action FROM perms p, hierarchy h WHERE h.child = %d AND h.parent = p.rolid ORDER BY action DESC, rolid", role); + + ci_thread_mutex_lock(&mtx); + retval = odbx_query (dbh, buf, strlen (buf)); + if (retval != ODBX_ERR_SUCCESS) { + ci_debug_printf (1, "Error executing SQL query '%s': %s\n", buf, odbx_error (dbh, retval)); + free (ncats); + rc = DBQueryErrorPolicy; + ci_thread_mutex_unlock(&mtx); + goto print_log; + } + + retval = odbx_result (dbh, &sth, NULL, 0); + ci_thread_mutex_unlock(&mtx); + if (retval < 0) { + ci_debug_printf (1, "Error getting SQL query result '%s': %s\n", buf, odbx_error (dbh, retval)); + free (ncats); + rc = DBQueryErrorPolicy; + goto print_log; + } + + // Check category list + val = NULL; + valsz = 1; + found = 0; + while ((retval = odbx_row_fetch (sth)) != 0) { + int cat, action; + unsigned *u; + + if (retval < 0) { + ci_debug_printf (1, "Error fetching result row '%s': %s\n", buf, odbx_error (dbh, retval)); + break; + } + + if (val != (void *)-1) { + char *ptr; + int len; + + len = strlen(odbx_field_value(sth, 0)) + + strlen(odbx_field_value(sth, 1)) + 2; + if ((ptr = realloc(val, valsz + len)) == NULL) { + free(val); + val = (void *)-1; + } else { + val = ptr; + asprintf(&ptr, "%s:%s ", + odbx_field_value(sth, 1), + odbx_field_value(sth, 0)); + if (ptr == NULL) { + free(val); + val = (void *)-1; + } else { + strcat(val, ptr); + valsz += len; + } + } + } + + cat = str2int (odbx_field_value (sth, 0)); + action = str2int (odbx_field_value (sth, 1)); + for (u = ncats; *u; u++) { + ci_debug_printf (9, "checking host category %d against REJECT and REDIRECT category %d\n", *u, cat); + if (cat == *u && !found) { + found = 1; + rc = action; + } + } + } + free (ncats); + odbx_result_free (sth); + + if (val && val != (void *)-1) { + ci_thread_mutex_lock(&mtx); + mc_add(mc, key, strlen(key), val, strlen(val) + 1, + CACHETTL, 0); + ci_thread_mutex_unlock(&mtx); + free(val); + } + +print_log: + // uname, ip, url, role, cats, action + syslog (SyslogPriority, "%s %s %s %s %s %s", + uname, + httpinf->client_ip, + httpinf->page, + role ? rname : "-", + cats ? cats : "-", + rc == 0 ? "ACCEPT" : rc == 1 ? "REJECT" : "REDIRECT" + ); + if (cats) free (cats); + return rc; +} + +static char *reject_message="

Permition deny!

"; +static char *redirect_message="

You are redirected!

"; +//static char *server_ip = "X-Server-IP"; + +int url_filter_check_preview(char *preview_data,int preview_data_len, ci_request_t *req){ + ci_headers_list_t* req_header; + struct url_filter_data *uc=ci_service_data(req); + struct http_info httpinf; + int rc; + + if((req_header=ci_http_request_headers(req))==NULL) /*It is not possible but who knows .....*/ + return CI_ERROR; + +// httpinf.server_ip = ci_headers_value (req->request_header, server_ip); +// ci_conn_remote_ip (req->connection, httpinf.server_ip); + httpinf.client_ip = ci_headers_value (req->request_header, ClientIPHeader); + httpinf.auth_user [0] = 0; + if (AuthUserEncoded) + ci_base64_decode (ci_headers_value (req->request_header, AuthUserHeader), httpinf.auth_user, MAX_USERNAME_LEN); + else + strncpy(httpinf.auth_user,ci_headers_value (req->request_header, AuthUserHeader),MAX_USERNAME_LEN); + + get_http_info(req,req_header, &httpinf); + + ci_debug_printf(9,"URL to host %s\n",httpinf.site); + ci_debug_printf(9,"URL page %s\n",httpinf.page); + + rc=check_destination(&httpinf, 1); + ci_debug_printf (5, "Action: %s\n", rc == 0 ? "ACCEPT" : rc == 1 ? "REJECT" : "REDIRECT"); + + if (!rc) { + /*if we are inside preview negotiation or client allow204 responces oudsite of preview then*/ + if(preview_data || ci_req_allow204(req)) + return CI_MOD_ALLOW204; + + /* + Squid does not support preview of data in reqmod requests neither 204 responces outside preview + so we need to read all the body if exists and send it back to squid. + Allocate a new body for it + */ + if(ci_req_hasbody(req)){ + int clen=ci_http_content_lenght(req)+100; + uc->body=ci_cached_file_new(clen); + } + + } else if (rc == 2 && RedirectUrl && *RedirectUrl) { + char buf [strlen (RedirectUrl) + 20]; + /*The URL is not a good one so....*/ + ci_debug_printf(9,"Oh!!! we are going to redirect this site.....\n"); + + uc->denied = 1; + uc->body=ci_cached_file_new(strlen(redirect_message)+10); + ci_http_response_create(req,1,1); /*Build the responce headers*/ + + ci_http_response_add_header(req,"HTTP/1.1 302 Found");/*Send an 302 Found http responce to web client*/ + ci_http_response_add_header(req,"Server: C-ICAP"); + snprintf (buf, sizeof buf, "Location: %s", RedirectUrl); + ci_http_response_add_header(req,buf); + ci_http_response_add_header(req,"Content-Type: text/html"); + ci_http_response_add_header(req,"Content-Language: en"); + + ci_cached_file_write(uc->body,redirect_message,strlen(redirect_message),1); + } else { + /*The URL is not a good one so....*/ + ci_debug_printf(9,"Oh!!! we are going to deny this site.....\n"); + + uc->denied = 1; + uc->body=ci_cached_file_new(strlen(reject_message)+10); + ci_http_response_create(req,1,1); /*Build the responce headers*/ + + ci_http_response_add_header(req,"HTTP/1.1 403 Forbidden");/*Send an 403 Forbidden http responce to web client*/ + ci_http_response_add_header(req,"Server: C-ICAP"); + ci_http_response_add_header(req,"Content-Type: text/html"); + ci_http_response_add_header(req,"Content-Language: en"); + + ci_cached_file_write(uc->body,reject_message,strlen(reject_message),1); + } + + unlock_data(req); + return CI_MOD_CONTINUE; +} + + +int url_filter_process(ci_request_t *req){ + +/* + printf("Buffer size=%d, Data size=%d\n ", + ((struct membuf *)b)->bufsize,((struct membuf *)b)->endpos); +*/ +// printf("url_filter process\n"); + return CI_MOD_DONE; +} + +int url_filter_io(char *wbuf, int *wlen, char *rbuf, int *rlen, int iseof, + ci_request_t * req) +{ + int ret; + struct url_filter_data *uc = ci_service_data(req); + if (!uc->body) + return CI_ERROR; + + ret = CI_OK; + if (uc->denied == 0) { + if (rbuf && rlen) { + *rlen = ci_cached_file_write(uc->body, rbuf, *rlen, iseof); + if (*rlen == CI_ERROR) + ret = CI_ERROR; + } + else if (iseof) + ci_cached_file_write(uc->body, NULL, 0, iseof); + } + + if (wbuf && wlen) { + *wlen = ci_cached_file_read(uc->body, wbuf, *wlen); + if (*wlen == CI_ERROR) + ret = CI_ERROR; + } + + return ret; +} + +static unsigned dotip2int (char *str) +{ + unsigned ip = 0, byte = 0; + + for (; *str; str++) { + if (*str == '.') { + ip <<= 8; + ip += byte; + byte = 0; + } else { + byte *= 10; + byte += *str - '0'; + } + } + ip <<= 8; + ip += byte; + return ip; +} + +static unsigned str2int (const char *str) +{ + unsigned ip = 0; + + if (!str) return 0; + for (; *str; str++) { + ip *= 10; + ip += *str - '0'; + } + return ip; +}