Browse files

Introducing rule filetime; this rule allows to match on access, creat…

…ion or modification time changes. Originally written to be run on an OpenStreetMap tile

server, together with handler_tile. This code also introduces the ability to have 'beta' modules, which are only enabled using --enable-beta. An open case to
me if this is handled correctly in the admin. now.

http://code.google.com/p/cherokee/issues/detail?id=683
  • Loading branch information...
1 parent 1d6ff06 commit e7daa3d8ee8d7e56a441c2a3ae939a879e66b3eb @skinkie committed Oct 14, 2011
Showing with 404 additions and 1 deletion.
  1. +2 −0 admin/consts.py
  2. +1 −0 admin/plugins/Makefile.am
  3. +102 −0 admin/plugins/filetime.py
  4. +19 −0 cherokee/Makefile.am
  5. +203 −0 cherokee/rule_filetime.c
  6. +67 −0 cherokee/rule_filetime.h
  7. +10 −1 configure.in
View
2 admin/consts.py
@@ -51,6 +51,7 @@
('', N_('None')),
('common', N_('List & Send')),
('file', N_('Static Content')),
+ ('tile', N_('Renderd Frontend')),
('dirlist', N_('Only Listing')),
('redir', N_('Redirection')),
('fcgi', N_('FastCGI')),
@@ -186,6 +187,7 @@
RULES = [
('directory', N_('Directory')),
('extensions', N_('Extensions')),
+ ('filetime', N_('File Time')),
('request', N_('Regular Expression')),
('header', N_('Header')),
('exists', N_('File Exists')),
View
1 admin/plugins/Makefile.am
@@ -21,6 +21,7 @@ extensions.py \
failover.py \
fcgi.py \
file.py \
+filetime.py \
from.py \
fullpath.py \
geoip.py \
View
102 admin/plugins/filetime.py
@@ -0,0 +1,102 @@
+# Cheroke Admin
+#
+# Authors:
+# Alvaro Lopez Ortega <alvaro@alobbs.com>
+# Stefan de Konink <stefan@konink.de>
+#
+# Copyright (C) 2009-2010 Alvaro Lopez Ortega
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2 of the GNU General Public
+# License as published by the Free Software Foundation.
+#
+# 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., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+
+import CTK
+
+from Rule import RulePlugin
+from util import *
+
+URL_APPLY = '/plugin/filetime/apply'
+
+NOTE_STATPROP = N_("The time propery of the file to match against.")
+NOTE_OPERATOR = N_("What operator should be used to match the property against the value.")
+NOTE_TIMESTAMP = N_("Unix timestamp")
+
+STATPROPS = [
+ ('', _('Choose')),
+ ('atime', _('Access Time')),
+ ('ctime', _('Creation Time')),
+ ('mtime', _('Modification Time'))
+]
+
+OPERATORS = [
+ ('', _('Choose')),
+ ('le', _('less equal')),
+ ('ge', _('greater equal')),
+ ('eq', _('equal')),
+ ('lenow', _('less equal now +')),
+ ('genow', _('greater equal now +'))
+]
+
+def commit():
+ # POST info
+ key = CTK.post.pop ('key', None)
+ vsrv_num = CTK.post.pop ('vsrv_num', None)
+ new_stat = CTK.post.pop ('tmp!stat', None)
+ new_time = CTK.post.pop ('tmp!time', None)
+ new_op = CTK.post.pop ('tmp!op', None)
+
+ # New entry
+ if new_stat:
+ next_rule, next_pre = cfg_vsrv_rule_get_next ('vserver!%s'%(vsrv_num))
+
+ CTK.cfg['%s!match'%(next_pre)] = 'filetime'
+ CTK.cfg['%s!match!stat'%(next_pre)] = new_stat
+ CTK.cfg['%s!match!time'%(next_pre)] = new_time
+ CTK.cfg['%s!match!op'%(next_pre)] = new_op
+
+ return {'ret': 'ok', 'redirect': '/vserver/%s/rule/%s' %(vsrv_num, next_rule)}
+
+ # Modifications
+ return CTK.cfg_apply_post()
+
+
+class Plugin_filetime (RulePlugin):
+ def __init__ (self, key, **kwargs):
+ RulePlugin.__init__ (self, key)
+ is_new = key.startswith('tmp')
+ props = ({},{'class': 'noauto'})[is_new]
+
+ op_widget = CTK.ComboCfg ('%s!op'%(key), OPERATORS, props)
+ op_val = CTK.cfg.get_val ('%s!op'%(key), 'regex')
+
+ table = CTK.PropsTable()
+ table.Add (_('Property'), CTK.ComboCfg('%s!stat'%(key), STATPROPS, props), _(NOTE_STATPROP))
+ table.Add (_('Operator'), op_widget, _(NOTE_OPERATOR))
+ table.Add (_('Unix Timestamp'), CTK.TextCfg('%s!time'%(key), False, props), _(NOTE_TIMESTAMP))
+
+ submit = CTK.Submitter (URL_APPLY)
+ submit += CTK.Hidden ('key', key)
+ submit += CTK.Hidden ('vsrv_num', kwargs.pop('vsrv_num', ''))
+ submit += table
+ self += submit
+
+ # Validation, and Public URLs
+ CTK.publish (URL_APPLY, commit, method="POST")
+
+ def GetName (self):
+ stat = CTK.cfg.get_val ('%s!stat' %(self.key), '')
+ time = CTK.cfg.get_val ('%s!time' %(self.key), '')
+ op = CTK.cfg.get_val ('%s!op' %(self.key), '')
+
+ return "%s %s %s %s" % (_("File"), stat, op, time)
View
19 cherokee/Makefile.am
@@ -151,6 +151,23 @@ endif
#
+# Rule filetime
+#
+rule_filetime = \
+rule_filetime.c \
+rule_filetime.h
+
+libplugin_filetime_la_LDFLAGS = $(module_ldflags)
+libplugin_filetime_la_SOURCES = $(rule_filetime)
+
+if STATIC_RULE_FILETIME
+static_rule_filetime_src = $(rule_filetime)
+else
+dynamic_rule_filetime_lib = libplugin_filetime.la
+endif
+
+
+#
# Rule request
#
rule_request = \
@@ -1502,6 +1519,7 @@ endif
libcherokee_server_la_SOURCES = \
$(static_rule_directory_src) \
$(static_rule_extensions_src) \
+$(static_rule_filetime_src) \
$(static_rule_request_src) \
$(static_rule_header_src) \
$(static_rule_exists_src) \
@@ -1696,6 +1714,7 @@ plugindir = "$(libdir)/cherokee"
plugin_LTLIBRARIES = \
$(dynamic_rule_directory_lib) \
$(dynamic_rule_extensions_lib) \
+$(dynamic_rule_filetime_lib) \
$(dynamic_rule_request_lib) \
$(dynamic_rule_header_lib) \
$(dynamic_rule_exists_lib) \
View
203 cherokee/rule_filetime.c
@@ -0,0 +1,203 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/* Cherokee
+ *
+ * Authors:
+ * Alvaro Lopez Ortega <alvaro@alobbs.com>
+ * Stefan de Konink <stefan@konink.de>
+ *
+ * Copyright (C) 2001-2011 Alvaro Lopez Ortega
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "common-internal.h"
+#include "bogotime.h"
+#include "rule_filetime.h"
+#include "plugin_loader.h"
+#include "connection-protected.h"
+#include "util.h"
+#include "thread.h"
+#include "dtm.h"
+#include "server-protected.h"
+
+#define ENTRIES "rule,filetime"
+
+PLUGIN_INFO_RULE_EASIEST_INIT(filetime);
+
+static ret_t
+configure (cherokee_rule_filetime_t *rule,
+ cherokee_config_node_t *conf,
+ cherokee_virtual_server_t *vsrv)
+{
+ ret_t ret;
+ cherokee_list_t *i;
+
+ UNUSED(vsrv);
+
+ cherokee_config_node_foreach (i, conf) {
+ cherokee_config_node_t *subconf = CONFIG_NODE(i);
+
+ if (equal_buf_str (&subconf->key, "stat")) {
+ if (equal_buf_str (&subconf->val, "atime")) {
+ rule->type = ft_atime;
+ } else if (equal_buf_str (&subconf->val, "ctime")) {
+ rule->type = ft_ctime;
+ } else if (equal_buf_str (&subconf->val, "mtime")) {
+ rule->type = ft_mtime;
+ } else {
+ LOG_CRITICAL (CHEROKEE_ERROR_RULE_NO_PROPERTY,
+ RULE(rule)->priority, "type");
+ return ret_error;
+ }
+ } else if (equal_buf_str (&subconf->key, "op")) {
+ if (equal_buf_str (&subconf->val, "eq")) {
+ rule->comparison = equal;
+ } else if (equal_buf_str (&subconf->val, "le")) {
+ rule->comparison = equalless;
+ } else if (equal_buf_str (&subconf->val, "ge")) {
+ rule->comparison = equalgreater;
+ } else if (equal_buf_str (&subconf->val, "lenow")) {
+ rule->comparison = equallessnow;
+ } else if (equal_buf_str (&subconf->val, "genow")) {
+ rule->comparison = equalgreaternow;
+ } else {
+ LOG_CRITICAL (CHEROKEE_ERROR_RULE_NO_PROPERTY,
+ RULE(rule)->priority, "comparison");
+ return ret_error;
+ }
+ } else if (equal_buf_str (&subconf->key, "time")) {
+ rule->time = atol (subconf->val.buf);
+ }
+ }
+
+ return ret_ok;
+}
+
+static ret_t
+_free (void *p)
+{
+ return ret_ok;
+}
+
+static ret_t
+match (cherokee_rule_filetime_t *rule,
+ cherokee_connection_t *conn,
+ cherokee_config_entry_t *ret_conf)
+{
+ ret_t ret;
+ struct stat nocache_info;
+ struct stat *info;
+ cherokee_iocache_entry_t *io_entry = NULL;
+ cherokee_server_t *srv = CONN_SRV(conn);
+
+ cherokee_buffer_t *tmp = THREAD_TMP_BUF1(CONN_THREAD(conn));
+
+ /* Path base */
+ cherokee_buffer_clean (tmp);
+
+ if (ret_conf->document_root != NULL) {
+ /* A previous non-final rule set a custom document root */
+ cherokee_buffer_add_buffer (tmp, ret_conf->document_root);
+ } else {
+ cherokee_buffer_add_buffer (tmp, &conn->local_directory);
+ }
+
+ cherokee_buffer_add_str (tmp, "/");
+
+ if (! cherokee_buffer_is_empty (&conn->web_directory)) {
+ cherokee_buffer_add (tmp,
+ conn->request.buf + conn->web_directory.len,
+ conn->request.len - conn->web_directory.len);
+ } else {
+ cherokee_buffer_add_buffer (tmp, &conn->request);
+ }
+
+ ret = cherokee_io_stat (srv->iocache,
+ tmp,
+ rule->use_iocache,
+ &nocache_info,
+ &io_entry,
+ &info);
+
+
+ if (ret == ret_ok) {
+ time_t time;
+ switch (rule->type) {
+ case ft_atime:
+ time = info->st_atime;
+ break;
+ case ft_ctime:
+ time = info->st_ctime;
+ break;
+ case ft_mtime:
+ time = info->st_mtime;
+ break;
+ }
+
+ ret = ret_not_found;
+
+ switch (rule->comparison) {
+ case equal:
+ if (time == rule->time) ret = ret_ok;
+ break;
+ case equalless:
+ if (time <= rule->time) ret = ret_ok;
+ break;
+ case equalgreater:
+ if (time >= rule->time) ret = ret_ok;
+ break;
+ case equallessnow:
+ if (time <= (cherokee_bogonow_now + rule->time)) ret = ret_ok;
+ break;
+ case equalgreaternow:
+ if (time >= (cherokee_bogonow_now + rule->time)) ret = ret_ok;
+ break;
+ }
+ } else {
+ ret = ret_not_found;
+ }
+
+ if (io_entry) {
+ cherokee_iocache_entry_unref (&io_entry);
+ }
+
+ return ret;
+}
+
+ret_t
+cherokee_rule_filetime_new (cherokee_rule_filetime_t **rule)
+{
+ CHEROKEE_NEW_STRUCT (n, rule_filetime);
+
+ /* Parent class constructor
+ */
+ cherokee_rule_init_base (RULE(n), PLUGIN_INFO_PTR(filetime));
+
+ /* Virtual methods
+ */
+ RULE(n)->match = (rule_func_match_t) match;
+ RULE(n)->configure = (rule_func_configure_t) configure;
+ MODULE(n)->free = (module_func_free_t) _free;
+
+ /* Properties
+ */
+ n->time = 0;
+ n->comparison = equalless;
+ n->type = ft_ctime;
+
+ *rule = n;
+ return ret_ok;
+}
View
67 cherokee/rule_filetime.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/* Cherokee
+ *
+ * Authors:
+ * Alvaro Lopez Ortega <alvaro@alobbs.com>
+ * Stefan de Konink <stefan@konink.de>
+ *
+ * Copyright (C) 2001-2011 Alvaro Lopez Ortega
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#if !defined (CHEROKEE_INSIDE_CHEROKEE_H) && !defined (CHEROKEE_COMPILATION)
+# error "Only <cherokee/cherokee.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef CHEROKEE_RULE_FILETIME_H
+#define CHEROKEE_RULE_FILETIME_H
+
+#include <cherokee/common.h>
+#include <cherokee/buffer.h>
+#include <cherokee/rule.h>
+#include <cherokee/list.h>
+
+CHEROKEE_BEGIN_DECLS
+
+typedef struct {
+ cherokee_rule_t rule;
+ cherokee_boolean_t use_iocache;
+
+ time_t time;
+
+ enum {
+ ft_atime,
+ ft_ctime,
+ ft_mtime
+ } type;
+
+ enum {
+ equal,
+ equalless,
+ equalgreater,
+ equallessnow,
+ equalgreaternow
+ } comparison;
+} cherokee_rule_filetime_t;
+
+#define RULE_FILETIME(x) ((cherokee_rule_filetime_t *)(x))
+
+ret_t cherokee_rule_filetime_new (cherokee_rule_filetime_t **rule);
+
+CHEROKEE_END_DECLS
+
+#endif /* CHEROKEE_RULE_FILETIME_H */
View
11 configure.in
@@ -1441,7 +1441,15 @@ AC_ARG_ENABLE(static-module,
modules="error_redir error_nn server_info file dirlist cgi fcgi scgi uwsgi proxy redir common ssi secdownload empty_gif drop admin custom_error dbslayer streaming gzip deflate ncsa combined custom pam ldap mysql htpasswd plain htdigest authlist round_robin ip_hash failover directory extensions request header exists fullpath method from bind tls geoip url_arg v_or wildcard rehost target_ip evhost post_track post_report libssl render_rrd rrd not and or"
-# Remove modules that will not be compiles
+beta_modules="filetime"
+
+# Include beta modules only when --enable-beta is provided
+#
+if test "x$is_beta" = "xyes"; then
+ modules="$modules $beta_modules"
+fi
+
+# Remove modules that will not be compiled
#
if test "x$have_pam" != "xyes"; then
modules=`echo $modules | sed s/pam//`
@@ -1537,6 +1545,7 @@ AM_CONDITIONAL(STATIC_BALANCER_FAILOVER, grep failover $conf_h >/dev/
AM_CONDITIONAL(STATIC_CRYPTOR_LIBSSL, grep libssl $conf_h >/dev/null)
AM_CONDITIONAL(STATIC_RULE_DIRECTORY, grep directory $conf_h >/dev/null)
AM_CONDITIONAL(STATIC_RULE_EXTENSIONS, grep extensions $conf_h >/dev/null)
+AM_CONDITIONAL(STATIC_RULE_FILETIME, grep filetime $conf_h >/dev/null)
AM_CONDITIONAL(STATIC_RULE_REQUEST, grep request $conf_h >/dev/null)
AM_CONDITIONAL(STATIC_RULE_HEADER, grep header $conf_h >/dev/null)
AM_CONDITIONAL(STATIC_RULE_EXISTS, grep exists $conf_h >/dev/null)

0 comments on commit e7daa3d

Please sign in to comment.