/*
 * Caudium - An extensible World Wide Web server
 * Copyright © 2001-2002 The Caudium Group
 * Copyright © 2001 Davies, Inc
 * 
 * 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.
 *
 */
/*
 * $Id: browserdeny.pike,v 1.1.2.4 2002/07/09 00:39:07 kiwi Exp $
 */
/*
 * See http://www.daviesinc.com/modules/ for more informations.
 */


#include <module.h>
inherit "module";
inherit "caudiumlib";

import Stdio;
import Array;

//! module: Browser Redirect Module
//!  For those of you that don't like web 'suckers' that screw up you stats 
//!  and cause general discontents, here is a quick module the tries to 
//!  address those issues. By default, the module will decline Teleport
//!  Pro and Unknown browser strings. Your Regexp is automatically lowercased
//!  and is stored in the startup process which means that you need to reload
//!  the module for changes to the Regexp's to take effects.<br /> Based on
//!  Chris Davies <a href="http://www.daviesinc.com/modules/">module.</a>
//! type: MODULE_FIRST
//! inherits: module
//! inherits: caudiumlib
//! cvs_version: $Id: browserdeny.pike,v 1.1.2.4 2002/07/09 00:39:07 kiwi Exp $

constant module_type = MODULE_FIRST;
constant module_name = "Browser Redirect Module";
constant module_doc  = "For those of you that don't like web 'suckers' that "
                       "screw up your stats and cause general discontent, "
                       "here's a quick module that tries to address those "
                       "issues.  By default, the module will decline Teleport "
                       "Pro and Unknown browser strings. Your Regexp is "
                       "automatically lowercased and is stored in the startup "
                       "process which means that you need to reload the "
                       "module for changes to the Regexp's to take effect."
                       "<br/>Based on Chris Davies <a href=\""
                       "http://www.daviesinc.com/modules/\">module.</a>";
constant thread_safe = 1;
constant cvs_version = "$Id: browserdeny.pike,v 1.1.2.4 2002/07/09 00:39:07 kiwi Exp $";
constant module_unique = 1;

void create() {
  defvar("regexpinclude", ".*",
         "Regexp Include Specification", TYPE_STRING,
         "An expression here will include processing for anything that matches this Pike Syntax Regexp<br />"
         "For Example:<br />.*<br />will include processing for all browsers.  id->useragent is automatically "
         "lowercased as is your regexp query");
  defvar("regexpexclude", "^(teleport|unknown)",
         "Regexp Exclude Specification", TYPE_STRING,
         "An expression here will exclude processing for anything that matches this Pike Syntax Regexp<br />"
         "For Example:<br />^(teleport|offline|ecatch|mass downloader|unknown)<br />"
         "will exclude processing for Teleport, Offline Explorer, eCatch, Mass Downloader and unknown "
         "browsers.  id->useragent is automatically lowercased as is your regexp query");
  defvar("nastymode", 0, "Nasty Redirect Mode", TYPE_FLAG,
         "If set to yes, this will redirect traffic to the Nasty Mode URL rather than give the error 403");
  defvar("nastyurl", "", "Nasty Mode URL", TYPE_STRING,
         "This is the URL to direct to if Nasty Redirect Mode is turned on"
         "http://www.tenmax.com/ is my personal favorite since they are the largest source of mechanical "
         "surfers");
  defvar("errmessage", "Need Human Browser", "Error 403 string to hand back", TYPE_STRING,
         "This is the message that is sent in the error string -- probably never seen by anyone");
}

object incl=0,excl=0;
int blocks=0;
void start(int num, object conf) {
  catch {
    if (strlen(QUERY(regexpinclude)))
      incl = Regexp(lower_case(QUERY(regexpinclude)));
    if (strlen(QUERY(regexpexclude)))
      excl = Regexp(lower_case(QUERY(regexpexclude)));
  };
}

mapping first_try(object id) {

  if (id->useragent && (incl && incl->match(lower_case(id->useragent))) ||
     (excl && !excl->match(lower_case(id->useragent))) )
    return(0);

  blocks++;

  if (QUERY(nastymode)) {
    return http_redirect(QUERY(nastyurl));
  }

  return http_low_answer( 403, QUERY(errmessage));
}
string status() {

  return(sprintf("%d surfer%s blocked.<br>\n", blocks, (blocks != 1) ? "s" : ""));
}

/* START AUTOGENERATED DEFVAR DOCS */

//! defvar: regexpinclude
//! An expression here will include processing for anything that matches this Pike Syntax Regexp<br />For Example:<br />.*<br />will include processing for all browsers.  id->useragent is automatically lowercased as is your regexp query
//!  type: TYPE_STRING
//!  name: Regexp Include Specification
//
//! defvar: regexpexclude
//! An expression here will exclude processing for anything that matches this Pike Syntax Regexp<br />For Example:<br />^(teleport|offline|ecatch|mass downloader|unknown)<br />will exclude processing for Teleport, Offline Explorer, eCatch, Mass Downloader and unknown browsers.  id->useragent is automatically lowercased as is your regexp query
//!  type: TYPE_STRING
//!  name: Regexp Exclude Specification
//
//! defvar: nastymode
//! If set to yes, this will redirect traffic to the Nasty Mode URL rather than give the error 403
//!  type: TYPE_FLAG
//!  name: Nasty Redirect Mode
//
//! defvar: nastyurl
//! This is the URL to direct to if Nasty Redirect Mode is turned onhttp://www.tenmax.com/ is my personal favorite since they are the largest source of mechanical surfers
//!  type: TYPE_STRING
//!  name: Nasty Mode URL
//
//! defvar: errmessage
//! This is the message that is sent in the error string -- probably never seen by anyone
//!  type: TYPE_STRING
//!  name: Error 403 string to hand back
//
