current GNUmakefile.in, 1.235, 1.236 cgi.c, 1.161, 1.162 cgisimple.c, 1.135, 1.136 cgisimple.h, 1.19, 1.20 configure.in, 1.191, 1.192 filters.c, 1.200, 1.201 filters.h, 1.46, 1.47 jcc.c, 1.441, 1.442 jcc.h, 1.35, 1.36 loadcfg.c, 1.147, 1.148 project.h, 1.212, 1.213 urlmatch.c, 1.87, 1.88

Fabian Keil <[email protected]>
Newsgroups gmane.comp.web.privoxy.cvs
Message-ID <[email protected]>
Update of /cvsroot/ijbswa/current
In directory sfp-cvs-1.v30.ch3.sourceforge.com:/tmp/cvs-serv6270

Modified Files:
	GNUmakefile.in cgi.c cgisimple.c cgisimple.h configure.in 
	filters.c filters.h jcc.c jcc.h loadcfg.c project.h urlmatch.c 
Log Message:
Implement client-specific tags

... which allow Privoxy admins to pre-define tags that
are set for all requests from clients that previously
opted-in through the CGI interface.

They are useful in multi-user setups where admins may
want to allow users to disable certain actions and filters
for themselves without affecting others.

In single-user setups they are useful to allow more
fine-grained toggling. For example to disable request
blocking while still crunching cookies, or to disable
experimental filters only.

This is an experimental feature, to enable it configure
with --enable-client-tags. The syntax and behaviour may
change in future versions.

Implements TODO list item #144 and #145.
Funded by a donation from Robert Klemme.


Index: project.h
===================================================================
RCS file: /cvsroot/ijbswa/current/project.h,v
retrieving revision 1.212
retrieving revision 1.213
diff -C2 -d -r1.212 -r1.213
*** project.h	16 Jan 2016 12:30:43 -0000	1.212
--- project.h	17 Mar 2016 10:40:53 -0000	1.213
***************
*** 401,404 ****
--- 401,407 ----
  #define PATTERN_SPEC_NO_RESPONSE_TAG_PATTERN 0x00000008UL
  
+ /** Pattern spec bitmap: It's a CLIENT-TAG pattern. */
+ #define PATTERN_SPEC_CLIENT_TAG_PATTERN      0x00000010UL
+ 
  /**
   * An I/O buffer.  Holds a string which can be appended to, and can have data
***************
*** 948,951 ****
--- 951,959 ----
     struct list tags[1];
  
+ #ifdef FEATURE_CLIENT_TAGS
+    /** List of all tags that apply to this client (assigned based on address) */
+    struct list client_tags[1];
+ #endif
+ 
     /** MIME-Type key, see CT_* above */
     unsigned int content_type;
***************
*** 1203,1206 ****
--- 1211,1223 ----
  #define NLOADERS 8
  
+ /**
+  * This struct represents a client-spcific-tag and it's description
+  */
+ struct client_tag_spec
+ {
+    char *name;        /**< Name from "client-specific-tag bla" directive */
+    char *description; /**< Description from "client-specific-tag-description " directive */
+    struct client_tag_spec *next; /**< The pointer for chaining. */
+ };
  
  /** configuration_spec::feature_flags: CGI actions editor. */
***************
*** 1325,1328 ****
--- 1342,1352 ----
  #endif /* def FEATURE_TRUST */
  
+ #ifdef FEATURE_CLIENT_TAGS
+    struct client_tag_spec client_tags[1];
+ 
+    /* Maximum number of seconds a temporarily enabled tag stays enabled. */
+    unsigned int client_tag_lifetime;
+ #endif /* def FEATURE_CLIENT_TAGS */
+ 
  #ifdef FEATURE_ACL
  

Index: configure.in
===================================================================
RCS file: /cvsroot/ijbswa/current/configure.in,v
retrieving revision 1.191
retrieving revision 1.192
diff -C2 -d -r1.191 -r1.192
*** configure.in	2 Feb 2016 13:08:17 -0000	1.191
--- configure.in	17 Mar 2016 10:40:53 -0000	1.192
***************
*** 983,986 ****
--- 983,996 ----
  fi])
  
+ AC_ARG_ENABLE(client-tags,
+ [  --enable-client-tags                Enable client-specific tags],
+ [if test $enableval = yes; then
+   FEATURE_CLIENT_TAGS_ONLY=""
+   AC_DEFINE(FEATURE_CLIENT_TAGS,1,[Define to enable client-specific tags.])
+  else
+   FEATURE_CLIENT_TAGS_ONLY="#"
+ fi])
+ AC_SUBST(FEATURE_CLIENT_TAGS_ONLY)
+ 
  dnl pcre/pcrs is needed for CGI anyway, so
  dnl the choice is only between static and

Index: GNUmakefile.in
===================================================================
RCS file: /cvsroot/ijbswa/current/GNUmakefile.in,v
retrieving revision 1.235
retrieving revision 1.236
diff -C2 -d -r1.235 -r1.236
*** GNUmakefile.in	13 Feb 2016 11:18:02 -0000	1.235
--- GNUmakefile.in	17 Mar 2016 10:40:53 -0000	1.236
***************
*** 191,194 ****
--- 191,197 ----
  C_HDRS = $(C_SRC:.c=.h) project.h actionlist.h
  
+ CLIENT_TAG_SRC = @[email protected]
+ CLIENT_TAG_OBJS = @FEATURE_CLIENT_TAGS_ONLY@client-tags.@OBJEXT@
+ 
  W32_SRC   = @[email protected] w32taskbar.c win32.c w32svrapi.c
  W32_FILES = @[email protected]
***************
*** 222,227 ****
  PTHREAD_LIB  = @PTHREAD_ONLY@@PTHREAD_LIB@
  
! SRCS         = $(C_SRC)  $(W32_SRC)  $(PCRS_SRC)  $(PCRE_SRC)  $(REGEX_SRC)
! OBJS         = $(C_OBJS) $(W32_OBJS) $(PCRS_OBJS) $(PCRE_OBJS) $(REGEX_OBJS)
  HDRS         = $(C_HDRS) $(W32_HDRS) $(PCRS_HDRS) $(PCRE_OBJS) $(REGEX_HDRS)
  LIBS         = @LIBS@ $(W32_LIB) $(SOCKET_LIB) $(PTHREAD_LIB)
--- 225,230 ----
  PTHREAD_LIB  = @PTHREAD_ONLY@@PTHREAD_LIB@
  
! SRCS         = $(C_SRC) $(CLIENT_TAG_SRC) $(W32_SRC)  $(PCRS_SRC)  $(PCRE_SRC)  $(REGEX_SRC)
! OBJS         = $(C_OBJS) $(CLIENT_TAG_OBJS) $(W32_OBJS) $(PCRS_OBJS) $(PCRE_OBJS) $(REGEX_OBJS)
  HDRS         = $(C_HDRS) $(W32_HDRS) $(PCRS_HDRS) $(PCRE_OBJS) $(REGEX_HDRS)
  LIBS         = @LIBS@ $(W32_LIB) $(SOCKET_LIB) $(PTHREAD_LIB)

Index: jcc.c
===================================================================
RCS file: /cvsroot/ijbswa/current/jcc.c,v
retrieving revision 1.441
retrieving revision 1.442
diff -C2 -d -r1.441 -r1.442
*** jcc.c	26 Feb 2016 12:29:38 -0000	1.441
--- jcc.c	17 Mar 2016 10:40:53 -0000	1.442
***************
*** 116,119 ****
--- 116,122 ----
  #include "loadcfg.h"
  #include "urlmatch.h"
+ #ifdef FEATURE_CLIENT_TAGS
+ #include "client-tags.h"
+ #endif
  
  const char jcc_h_rcs[] = JCC_H_VERSION;
***************
*** 186,189 ****
--- 189,195 ----
  privoxy_mutex_t external_filter_mutex;
  #endif
+ #ifdef FEATURE_CLIENT_TAGS
+ privoxy_mutex_t client_tags_mutex;
+ #endif
  
  #if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R)
***************
*** 1843,1846 ****
--- 1849,1855 ----
     http = csp->http;
  
+ #if FEATURE_CLIENT_TAGS
+    get_tag_list_for_client(csp->client_tags, csp->ip_addr_str);
+ #endif
     if (receive_client_request(csp) != JB_ERR_OK)
     {
***************
*** 2814,2817 ****
--- 2823,2829 ----
     destroy_list(csp->headers);
     destroy_list(csp->tags);
+ #ifdef FEATURE_CLIENT_TAGS
+    destroy_list(csp->client_tags);
+ #endif
     free_current_action(csp->action);
     if (NULL != csp->fwd)
***************
*** 3247,3250 ****
--- 3259,3265 ----
     privoxy_mutex_init(&external_filter_mutex);
  #endif
+ #ifdef FEATURE_CLIENT_TAGS
+    privoxy_mutex_init(&client_tags_mutex);
+ #endif
  
     /*

Index: cgi.c
===================================================================
RCS file: /cvsroot/ijbswa/current/cgi.c,v
retrieving revision 1.161
retrieving revision 1.162
diff -C2 -d -r1.161 -r1.162
*** cgi.c	26 Feb 2016 12:32:26 -0000	1.161
--- cgi.c	17 Mar 2016 10:40:53 -0000	1.162
***************
*** 101,104 ****
--- 101,110 ----
           "View the source code version numbers",
            TRUE },
+ #ifdef FEATURE_CLIENT_TAGS
+    { "show-client-tags",
+          cgi_show_client_tags,
+          "Show the tags that can be set based on the client's address (opt-in)",
+           FALSE },
+ #endif
     { "show-request",
           cgi_show_request,

Index: urlmatch.c
===================================================================
RCS file: /cvsroot/ijbswa/current/urlmatch.c,v
retrieving revision 1.87
retrieving revision 1.88
diff -C2 -d -r1.87 -r1.88
*** urlmatch.c	26 Feb 2016 12:29:39 -0000	1.87
--- urlmatch.c	17 Mar 2016 10:40:53 -0000	1.88
***************
*** 1162,1165 ****
--- 1162,1168 ----
     } tag_pattern[] = {
        { "TAG:",              4, PATTERN_SPEC_TAG_PATTERN},
+  #ifdef FEATURE_CLIENT_TAGS
+       { "CLIENT-TAG:",      11, PATTERN_SPEC_CLIENT_TAG_PATTERN},
+  #endif
        { "NO-REQUEST-TAG:",  15, PATTERN_SPEC_NO_REQUEST_TAG_PATTERN},
        { "NO-RESPONSE-TAG:", 16, PATTERN_SPEC_NO_RESPONSE_TAG_PATTERN}

Index: filters.h
===================================================================
RCS file: /cvsroot/ijbswa/current/filters.h,v
retrieving revision 1.46
retrieving revision 1.47
diff -C2 -d -r1.46 -r1.47
*** filters.h	24 Dec 2013 13:32:51 -0000	1.46
--- filters.h	17 Mar 2016 10:40:53 -0000	1.47
***************
*** 76,82 ****
  extern void get_url_actions(struct client_state *csp,
                              struct http_request *http);
- extern void apply_url_actions(struct current_action_spec *action,
-                               struct http_request *http,
-                               struct url_actions *b);
  
  extern struct re_filterfile_spec *get_filter(const struct client_state *csp,
--- 76,79 ----

Index: cgisimple.c
===================================================================
RCS file: /cvsroot/ijbswa/current/cgisimple.c,v
retrieving revision 1.135
retrieving revision 1.136
diff -C2 -d -r1.135 -r1.136
*** cgisimple.c	4 Mar 2016 13:22:22 -0000	1.135
--- cgisimple.c	17 Mar 2016 10:40:53 -0000	1.136
***************
*** 61,64 ****
--- 61,67 ----
  #include "urlmatch.h"
  #include "errlog.h"
+ #ifdef FEATURE_CLIENT_TAGS
+ #include "client-tags.h"
+ #endif
  
  const char cgisimple_h_rcs[] = CGISIMPLE_H_VERSION;
***************
*** 272,275 ****
--- 275,408 ----
  
  
+ #ifdef FEATURE_CLIENT_TAGS
+ /*********************************************************************
+  *
+  * Function    :  cgi_show_client_tags
+  *
+  * Description :  Shows the tags that can be set based on the client
+  *                address (opt-in).
+  *
+  * Parameters  :
+  *          1  :  csp = Current client state (buffers, headers, etc...)
+  *          2  :  rsp = http_response data structure for output
+  *          3  :  parameters = map of cgi parameters
+  *
+  * CGI Parameters : none
+  *
+  * Returns     :  JB_ERR_OK on success
+  *                JB_ERR_MEMORY on out-of-memory error.
+  *
+  *********************************************************************/
+ jb_err cgi_show_client_tags(struct client_state *csp,
+                         struct http_response *rsp,
+                         const struct map *parameters)
+ {
+    struct map *exports;
+    struct client_tag_spec *this_tag;
+    jb_err err = JB_ERR_OK;
+    const char *toggled_tag;
+    const char *toggle_state;
+    const char *tag_expires;
+    time_t time_to_live;
+    char *client_tags = strdup_or_die("");
+    char buf[1000];
+ 
+    assert(csp);
+    assert(rsp);
+    assert(parameters);
+ 
+    if (NULL == (exports = default_exports(csp, "show-client-tags")))
+    {
+       return JB_ERR_MEMORY;
+    }
+ 
+    toggled_tag = lookup(parameters, "tag");
+    if (*toggled_tag != '\0')
+    {
+       tag_expires = lookup(parameters, "expires");
+       if (*tag_expires == '0')
+       {
+          time_to_live = 0;
+       }
+       else
+       {
+          time_to_live = csp->config->client_tag_lifetime;
+       }
+       toggle_state = lookup(parameters, "toggle-state");
+       if (*toggle_state == '1')
+       {
+          enable_client_specific_tag(csp, toggled_tag, time_to_live);
+       }
+       else
+       {
+          disable_client_specific_tag(csp, toggled_tag);
+       }
+    }
+ 
+    this_tag = csp->config->client_tags;
+    if (this_tag->name == NULL)
+    {
+       if (!err) err = string_append(&client_tags, "<p>No tags available.</p>\n");
+    }
+    else
+    {
+       if (!err)
+       {
+          err = string_append(&client_tags, "<table border=\"1\">\n"
+             "<tr><th>Tag name</th>\n"
+             "<th>Current state</th><th>Change state</th><th>Description</th></tr>\n");
+       }
+       while ((this_tag != NULL) && (this_tag->name != NULL))
+       {
+          int tag_state;
+ 
+          privoxy_mutex_lock(&client_tags_mutex);
+          tag_state = client_has_requested_tag(csp->ip_addr_str, this_tag->name);
+          privoxy_mutex_unlock(&client_tags_mutex);
+          if (!err) err = string_append(&client_tags, "<tr><td>");
+          if (!err) err = string_append(&client_tags, this_tag->name);
+          if (!err) err = string_append(&client_tags, "</td><td>");
+          if (!err) err = string_append(&client_tags, tag_state == 1 ? "Enabled" : "Disabled");
+          snprintf(buf, sizeof(buf),
+             "</td><td><a href=\"/show-client-tags?tag=%s&toggle-state=%d&amp;expires=0\">%s</a>",
+             this_tag->name, !tag_state, tag_state == 1 ? "Disable" : "Enable");
+          if (!err) err = string_append(&client_tags, buf);
+          if (tag_state == 0)
+          {
+             snprintf(buf, sizeof(buf), ". <a href=\"/show-client-tags?"
+                "tag=%s&amp;toggle-state=1&amp;expires=1\">Enable temporarily</a>",
+                this_tag->name);
+             if (!err) err = string_append(&client_tags, buf);
+          }
+          if (!err) err = string_append(&client_tags, "</td><td>");
+          if (!err) err = string_append(&client_tags, this_tag->description);
+          if (!err) err = string_append(&client_tags, "</td></tr>\n");
+          if (err)
+          {
+             free_map(exports);
+             return JB_ERR_MEMORY;
+          }
+          this_tag = this_tag->next;
+       }
+       if (!err) err = string_append(&client_tags, "</table>\n");
+    }
+ 
+    if (map(exports, "client-tags", 1, client_tags, 0))
+    {
+       free_map(exports);
+       return JB_ERR_MEMORY;
+    }
+ 
+    if (map(exports, "client-ip-addr", 1, csp->ip_addr_str, 1))
+    {
+       free_map(exports);
+       return JB_ERR_MEMORY;
+    }
+ 
+    return template_fill_for_cgi(csp, "show-client-tags", exports, rsp);
+ }
+ #endif /* def FEATURE_CLIENT_TAGS */
+ 
+ 
  /*********************************************************************
   *
***************
*** 1568,1571 ****
--- 1701,1712 ----
        },
        {
+          "FEATURE_CLIENT_TAGS",
+ #ifdef FEATURE_CLIENT_TAGS
+          1,
+ #else
+          0,
+ #endif
+       },
+       {
           "FEATURE_COMPRESSION",
  #ifdef FEATURE_COMPRESSION

Index: jcc.h
===================================================================
RCS file: /cvsroot/ijbswa/current/jcc.h,v
retrieving revision 1.35
retrieving revision 1.36
diff -C2 -d -r1.35 -r1.36
*** jcc.h	2 Jun 2014 06:22:21 -0000	1.35
--- jcc.h	17 Mar 2016 10:40:53 -0000	1.36
***************
*** 84,87 ****
--- 84,91 ----
  #endif
  
+ #ifdef FEATURE_CLIENT_TAGS
+ extern privoxy_mutex_t client_tags_mutex;
+ #endif
+ 
  #ifndef HAVE_GMTIME_R
  extern privoxy_mutex_t gmtime_mutex;

Index: cgisimple.h
===================================================================
RCS file: /cvsroot/ijbswa/current/cgisimple.h,v
retrieving revision 1.19
retrieving revision 1.20
diff -C2 -d -r1.19 -r1.20
*** cgisimple.h	24 Nov 2013 14:23:28 -0000	1.19
--- cgisimple.h	17 Mar 2016 10:40:53 -0000	1.20
***************
*** 69,72 ****
--- 69,77 ----
                                  struct http_response *rsp,
                                  const struct map *parameters);
+ #ifdef FEATURE_CLIENT_TAGS
+ extern jb_err cgi_show_client_tags(struct client_state *csp,
+                                    struct http_response *rsp,
+                                    const struct map *parameters);
+ #endif
  extern jb_err cgi_transparent_image (struct client_state *csp,
                                       struct http_response *rsp,

Index: filters.c
===================================================================
RCS file: /cvsroot/ijbswa/current/filters.c,v
retrieving revision 1.200
retrieving revision 1.201
diff -C2 -d -r1.200 -r1.201
*** filters.c	26 Feb 2016 12:29:38 -0000	1.200
--- filters.c	17 Mar 2016 10:40:53 -0000	1.201
***************
*** 71,74 ****
--- 71,77 ----
  #include "urlmatch.h"
  #include "loaders.h"
+ #ifdef FEATURE_CLIENT_TAGS
+ #include "client-tags.h"
+ #endif
  
  #ifdef _WIN32
***************
*** 82,85 ****
--- 85,94 ----
  static jb_err remove_chunked_transfer_coding(char *buffer, size_t *size);
  static jb_err prepare_for_filtering(struct client_state *csp);
+ static void apply_url_actions(struct current_action_spec *action,
+                               struct http_request *http,
+ #ifdef FEATURE_CLIENT_TAGS
+                               const struct list *client_tags,
+ #endif
+                               struct url_actions *b);
  
  #ifdef FEATURE_ACL
***************
*** 2323,2327 ****
--- 2332,2340 ----
        }
  
+ #ifdef FEATURE_CLIENT_TAGS
+       apply_url_actions(csp->action, http, csp->client_tags, b);
+ #else
        apply_url_actions(csp->action, http, b);
+ #endif
     }
  
***************
*** 2329,2333 ****
  }
  
- 
  /*********************************************************************
   *
--- 2342,2345 ----
***************
*** 2339,2350 ****
   *          1  :  action = Destination.
   *          2  :  http = Current URL
!  *          3  :  b = list of URL actions to apply
   *
   * Returns     :  N/A
   *
   *********************************************************************/
! void apply_url_actions(struct current_action_spec *action,
!                        struct http_request *http,
!                        struct url_actions *b)
  {
     if (b == NULL)
--- 2351,2366 ----
   *          1  :  action = Destination.
   *          2  :  http = Current URL
!  *          3  :  client_tags = list of client tags
!  *          4  :  b = list of URL actions to apply
   *
   * Returns     :  N/A
   *
   *********************************************************************/
! static void apply_url_actions(struct current_action_spec *action,
!                               struct http_request *http,
! #ifdef FEATURE_CLIENT_TAGS
!                               const struct list *client_tags,
! #endif
!                               struct url_actions *b)
  {
     if (b == NULL)
***************
*** 2360,2363 ****
--- 2376,2385 ----
           merge_current_action(action, b->action);
        }
+ #ifdef FEATURE_CLIENT_TAGS
+       if (client_tag_match(b->url, client_tags))
+       {
+          merge_current_action(action, b->action);
+       }
+ #endif
     }
  }

Index: loadcfg.c
===================================================================
RCS file: /cvsroot/ijbswa/current/loadcfg.c,v
retrieving revision 1.147
retrieving revision 1.148
diff -C2 -d -r1.147 -r1.148
*** loadcfg.c	26 Feb 2016 12:30:59 -0000	1.147
--- loadcfg.c	17 Mar 2016 10:40:53 -0000	1.148
***************
*** 125,128 ****
--- 125,130 ----
  #define hash_buffer_limit                1881726070U /* "buffer-limit */
  #define hash_client_header_order         2701453514U /* "client-header-order" */
+ #define hash_client_specific_tag         3353703383U /* "client-specific-tag" */
+ #define hash_client_tag_lifetime          647957580U /* "client-tag-lifetime" */
  #define hash_compression_level           2464423563U /* "compression-level" */
  #define hash_confdir                        1978389U /* "confdir" */
***************
*** 177,180 ****
--- 179,185 ----
  
  static void savearg(char *command, char *argument, struct configuration_spec * config);
+ #ifdef FEATURE_CLIENT_TAGS
+ static void free_client_specific_tags(struct client_tag_spec *tag_list);
+ #endif
  
  /*********************************************************************
***************
*** 254,257 ****
--- 259,266 ----
  #endif /* def FEATURE_TRUST */
  
+ #ifdef FEATURE_CLIENT_TAGS
+    free_client_specific_tags(config->client_tags);
+ #endif
+ 
     freez(config);
  }
***************
*** 282,285 ****
--- 291,373 ----
  
  
+ #ifdef FEATURE_CLIENT_TAGS
+ /*********************************************************************
+  *
+  * Function    :  register_tag
+  *
+  * Description :  Registers a client-specific-tag and its description
+  *
+  * Parameters  :
+  *          1  :  config: The tag list
+  *          2  :  name:  The name of the client-specific-tag
+  *          3  :  description: The human-readable description for the tag
+  *
+  * Returns     :  N/A
+  *
+  *********************************************************************/
+ static void register_tag(struct client_tag_spec *tag_list,
+    const char *name, const char *description)
+ {
+    struct client_tag_spec *new_tag;
+    struct client_tag_spec *last_tag;
+ 
+    last_tag = tag_list;
+    while (last_tag->next != NULL)
+    {
+       last_tag = last_tag->next;
+    }
+    if (last_tag->name == NULL)
+    {
+       /* First entry */
+       new_tag = last_tag;
+    }
+    else
+    {
+       new_tag = zalloc_or_die(sizeof(struct client_tag_spec));
+    }
+    new_tag->name = strdup_or_die(name);
+    new_tag->description = strdup_or_die(description);
+    if (new_tag != last_tag)
+    {
+       last_tag->next = new_tag;
+    }
+ }
+ 
+ 
+ /*********************************************************************
+  *
+  * Function    :  free_client_specific_tags
+  *
+  * Description :  Frees client-specific tags and their descriptions
+  *
+  * Parameters  :
+  *          1  :  tag_list: The tag list to free
+  *
+  * Returns     :  N/A
+  *
+  *********************************************************************/
+ static void free_client_specific_tags(struct client_tag_spec *tag_list)
+ {
+    struct client_tag_spec *this_tag;
+    struct client_tag_spec *next_tag;
+ 
+    next_tag = tag_list;
+    do
+    {
+       this_tag = next_tag;
+       next_tag = next_tag->next;
+ 
+       freez(this_tag->name);
+       freez(this_tag->description);
+ 
+       if (this_tag != tag_list)
+       {
+          freez(this_tag);
+       }
+    } while (next_tag != NULL);
+ }
+ #endif /* def FEATURE_CLIENT_TAGS */
+ 
+ 
  /*********************************************************************
   *
***************
*** 669,672 ****
--- 757,803 ----
  
  /* *************************************************************************
+  * client-specific-tag tag-name description
+  * *************************************************************************/
+ #ifdef FEATURE_CLIENT_TAGS
+          case hash_client_specific_tag:
+             {
+                char *name;
+                char *description;
+ 
+                name = arg;
+                description = strstr(arg, " ");
+                if (description == NULL)
+                {
+                   log_error(LOG_LEVEL_FATAL,
+                      "client-specific-tag '%s' lacks a description.", name);
+                }
+                *description = '\0';
+                description++;
+                register_tag(config->client_tags, name, description);
+             }
+             break;
+ #endif /* def FEATURE_CLIENT_TAGS */
+ 
+ /* *************************************************************************
+  * client-tag-lifetime ttl
+  * *************************************************************************/
+ #ifdef FEATURE_CLIENT_TAGS
+          case hash_client_tag_lifetime:
+          {
+             int ttl = parse_numeric_value(cmd, arg);
+             if (0 <= ttl)
+             {
+                config->client_tag_lifetime = (unsigned)ttl;
+             }
+             else
+             {
+                log_error(LOG_LEVEL_FATAL,
+                   "client-tag-lifetime can't be negative.");
+             }
+             break;
+          }
+ #endif /* def FEATURE_CLIENT_TAGS */
+ 
+ /* *************************************************************************
   * confdir directory-name
   * *************************************************************************/


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785231&iu=/4140
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.