tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cos...@apache.org
Subject cvs commit: jakarta-tomcat-connectors/jk/native2/common jk_ajp14.c jk_ajp_common.c jk_channel_socket.c jk_connect.c jk_context.c jk_env.c jk_handler_discovery.c jk_handler_logon.c jk_logger.c jk_map.c jk_md5.c jk_msg_buff.c jk_nwmain.c jk_pool.c jk_registry.c jk_util.c
Date Sat, 01 Dec 2001 22:38:40 GMT
costin      01/12/01 14:38:40

  Added:       jk/native2/common jk_ajp14.c jk_ajp_common.c
                        jk_channel_socket.c jk_connect.c jk_context.c
                        jk_env.c jk_handler_discovery.c jk_handler_logon.c
                        jk_logger.c jk_map.c jk_md5.c jk_msg_buff.c
                        jk_nwmain.c jk_pool.c jk_registry.c jk_util.c
  Log:
  All other files from common, with minor modifications.
  
  Revision  Changes    Path
  1.1                  jakarta-tomcat-connectors/jk/native2/common/jk_ajp14.c
  
  Index: jk_ajp14.c
  ===================================================================
  /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil-*- */
  /* ========================================================================= *
   *                                                                           *
   *                 The Apache Software License,  Version 1.1                 *
   *                                                                           *
   *          Copyright (c) 1999-2001 The Apache Software Foundation.          *
   *                           All rights reserved.                            *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * Redistribution and use in source and binary forms,  with or without modi- *
   * fication, are permitted provided that the following conditions are met:   *
   *                                                                           *
   * 1. Redistributions of source code  must retain the above copyright notice *
   *    notice, this list of conditions and the following disclaimer.          *
   *                                                                           *
   * 2. Redistributions  in binary  form  must  reproduce the  above copyright *
   *    notice,  this list of conditions  and the following  disclaimer in the *
   *    documentation and/or other materials provided with the distribution.   *
   *                                                                           *
   * 3. The end-user documentation  included with the redistribution,  if any, *
   *    must include the following acknowlegement:                             *
   *                                                                           *
   *       "This product includes  software developed  by the Apache  Software *
   *        Foundation <http://www.apache.org/>."                              *
   *                                                                           *
   *    Alternately, this acknowlegement may appear in the software itself, if *
   *    and wherever such third-party acknowlegements normally appear.         *
   *                                                                           *
   * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software     *
   *    Foundation"  must not be used  to endorse or promote  products derived *
   *    from this  software without  prior  written  permission.  For  written *
   *    permission, please contact <apache@apache.org>.                        *
   *                                                                           *
   * 5. Products derived from this software may not be called "Apache" nor may *
   *    "Apache" appear in their names without prior written permission of the *
   *    Apache Software Foundation.                                            *
   *                                                                           *
   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
   * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY *
   * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL *
   * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY *
   * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL *
   * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS *
   * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) *
   * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT, *
   * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
   * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE *
   * POSSIBILITY OF SUCH DAMAGE.                                               *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * This software  consists of voluntary  contributions made  by many indivi- *
   * duals on behalf of the  Apache Software Foundation.  For more information *
   * on the Apache Software Foundation, please see <http://www.apache.org/>.   *
   *                                                                           *
   * ========================================================================= */
  
  /***************************************************************************
   * Description: Next generation bi-directional protocol handler.           *
   * Author:      Henri Gomez <hgomez@slib.fr>                               *
   * Version:     $Revision: 1.1 $                                           *
   ***************************************************************************/
  
  
  #include "jk_global.h"
  #include "jk_util.h"
  #include "jk_map.h"
  #include "jk_ajp_common.h"
  #include "jk_ajp14.h"
  #include "jk_md5.h"
  
  
  /* 
   * Build the Shutdown Cmd
   *
   * +-----------------------+---------------------------------------+
   * | SHUTDOWN CMD (1 byte) | MD5 of RANDOM + SECRET KEY (32 chars) |
   * +-----------------------+---------------------------------------+
   *
   */
  
  int ajp14_marshal_shutdown_into_msgb(jk_msg_buf_t       *msg,
                                       jk_login_service_t *s,
                                       jk_logger_t        *l)
  {
      jk_log(l, JK_LOG_DEBUG, "Into ajp14_marshal_shutdown_into_msgb\n");
  
      /* To be on the safe side */
      jk_b_reset(msg);
  
      /*
       * SHUTDOWN CMD
       */
      if (jk_b_append_byte(msg, AJP14_SHUTDOWN_CMD))
          return JK_FALSE;
  
      /*
       * COMPUTED-SEED
       */
       if (jk_b_append_bytes(msg, (const unsigned char *)s->computed_key, AJP14_COMPUTED_KEY_LEN)) {
          jk_log(l, JK_LOG_ERROR, "Error ajp14_marshal_shutdown_into_msgb - Error appending the COMPUTED MD5 bytes\n");
          return JK_FALSE;
      }
  
  	return JK_TRUE;
  }
  
  /*
   * Decode the Shutdown Nok Command
   *
   * +----------------------+-----------------------+
   * | SHUTNOK CMD (1 byte) | FAILURE CODE (32bits) |
   * +----------------------+-----------------------+
   *
   */
  int ajp14_unmarshal_shutdown_nok(jk_msg_buf_t *msg,
                                   jk_logger_t  *l)
  {
      unsigned long   status;
  
      jk_log(l, JK_LOG_DEBUG, "Into ajp14_unmarshal_shutdown_nok\n");
  
      status = jk_b_get_long(msg);
  
      if (status == 0xFFFFFFFF) {
          jk_log(l, JK_LOG_ERROR, "Error ajp14_unmarshal_shutdown_nok - can't get failure code\n");
          return JK_FALSE;
      }
  
      jk_log(l, JK_LOG_INFO, "Can't shutdown servlet engine - code %08lx", status);
      return JK_TRUE;
  }
  
  /*
   * Build the Unknown Packet
   *
   * +-----------------------------+---------------------------------+------------------------------+
   * | UNKNOWN PACKET CMD (1 byte) | UNHANDLED MESSAGE SIZE (16bits) | UNHANDLED MESSAGE (bytes...) |
   * +-----------------------------+---------------------------------+------------------------------+
   *
   */
  
  int ajp14_marshal_unknown_packet_into_msgb(jk_msg_buf_t		*msg,
                                             jk_msg_buf_t		*unk,
                                             jk_logger_t  	*l)
  {
  	jk_log(l, JK_LOG_DEBUG, "Into ajp14_marshal_unknown_packet_into_msgb\n");
  
  	/* To be on the safe side */
  	jk_b_reset(msg);
  
  	/*
   	 * UNKNOWN PACKET CMD
  	 */
  	if (jk_b_append_byte(msg, AJP14_UNKNOW_PACKET_CMD))
  		return JK_FALSE;
  
  	/*
  	 * UNHANDLED MESSAGE SIZE
  	 */
  	if (jk_b_append_int(msg, (unsigned short) jk_b_get_len(unk)))
  		return JK_FALSE;
  
  	/*
  	 * UNHANDLED MESSAGE (Question : Did we have to send all the message or only part of)
  	 *					 (           ie: only 1k max								    )
  	 */
  	if (jk_b_append_bytes(msg, jk_b_get_buff(unk), jk_b_get_len(unk))) {
          jk_log(l, JK_LOG_ERROR, "Error ajp14_marshal_unknown_packet_into_msgb - Error appending the UNHANDLED MESSAGE\n");
          return JK_FALSE;
      }
  
      return JK_TRUE;
  }
  
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/common/jk_ajp_common.c
  
  Index: jk_ajp_common.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 The Apache Software License,  Version 1.1                 *
   *                                                                           *
   *          Copyright (c) 1999-2001 The Apache Software Foundation.          *
   *                           All rights reserved.                            *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * Redistribution and use in source and binary forms,  with or without modi- *
   * fication, are permitted provided that the following conditions are met:   *
   *                                                                           *
   * 1. Redistributions of source code  must retain the above copyright notice *
   *    notice, this list of conditions and the following disclaimer.          *
   *                                                                           *
   * 2. Redistributions  in binary  form  must  reproduce the  above copyright *
   *    notice,  this list of conditions  and the following  disclaimer in the *
   *    documentation and/or other materials provided with the distribution.   *
   *                                                                           *
   * 3. The end-user documentation  included with the redistribution,  if any, *
   *    must include the following acknowlegement:                             *
   *                                                                           *
   *       "This product includes  software developed  by the Apache  Software *
   *        Foundation <http://www.apache.org/>."                              *
   *                                                                           *
   *    Alternately, this acknowlegement may appear in the software itself, if *
   *    and wherever such third-party acknowlegements normally appear.         *
   *                                                                           *
   * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software     *
   *    Foundation"  must not be used  to endorse or promote  products derived *
   *    from this  software without  prior  written  permission.  For  written *
   *    permission, please contact <apache@apache.org>.                        *
   *                                                                           *
   * 5. Products derived from this software may not be called "Apache" nor may *
   *    "Apache" appear in their names without prior written permission of the *
   *    Apache Software Foundation.                                            *
   *                                                                           *
   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
   * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY *
   * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL *
   * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY *
   * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL *
   * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS *
   * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) *
   * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT, *
   * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
   * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE *
   * POSSIBILITY OF SUCH DAMAGE.                                               *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * This software  consists of voluntary  contributions made  by many indivi- *
   * duals on behalf of the  Apache Software Foundation.  For more information *
   * on the Apache Software Foundation, please see <http://www.apache.org/>.   *
   *                                                                           *
   * ========================================================================= */
  
  /***************************************************************************
   * Description: common stuff for bi-directional protocols ajp13/ajp14.     *
   * Author:      Gal Shachor <shachor@il.ibm.com>                           *
   * Author:      Henri Gomez <hgomez@slib.fr>                               *
   * Version:     $Revision: 1.1 $                                           *
   ***************************************************************************/
  
  
  #include "jk_global.h"
  #include "jk_util.h"
  #include "jk_ajp_common.h"
  #include "jk_ajp14.h"
  #include "jk_connect.h"
  #include "jk_channel.h"
  #include "jk_env.h"
  
  
  const char *response_trans_headers[] = {
      "Content-Type", 
      "Content-Language", 
      "Content-Length", 
      "Date", 
      "Last-Modified", 
      "Location", 
      "Set-Cookie", 
      "Set-Cookie2", 
      "Servlet-Engine", 
      "Status", 
      "WWW-Authenticate"
  };
  
  static const char *long_res_header_for_sc(int sc) 
  {
      const char *rc = NULL;
      if(sc <= SC_RES_HEADERS_NUM && sc > 0) {
          rc = response_trans_headers[sc - 1];
      }
  
      return rc;
  }
  
  
  static int sc_for_req_method(const char    *method,
                               unsigned char *sc) 
  {
      int rc = JK_TRUE;
      if(0 == strcmp(method, "GET")) {
          *sc = SC_M_GET;
      } else if(0 == strcmp(method, "POST")) {
          *sc = SC_M_POST;
      } else if(0 == strcmp(method, "HEAD")) {
          *sc = SC_M_HEAD;
      } else if(0 == strcmp(method, "PUT")) {
          *sc = SC_M_PUT;
      } else if(0 == strcmp(method, "DELETE")) {
          *sc = SC_M_DELETE;
      } else if(0 == strcmp(method, "OPTIONS")) {
          *sc = SC_M_OPTIONS;
      } else if(0 == strcmp(method, "TRACE")) {
          *sc = SC_M_TRACE;
      } else if(0 == strcmp(method, "PROPFIND")) {
  	*sc = SC_M_PROPFIND;
      } else if(0 == strcmp(method, "PROPPATCH")) {
  	*sc = SC_M_PROPPATCH;
      } else if(0 == strcmp(method, "MKCOL")) {
  	*sc = SC_M_MKCOL;
      } else if(0 == strcmp(method, "COPY")) {
  	*sc = SC_M_COPY;
      } else if(0 == strcmp(method, "MOVE")) {
  	*sc = SC_M_MOVE;
      } else if(0 == strcmp(method, "LOCK")) {
  	*sc = SC_M_LOCK;
      } else if(0 == strcmp(method, "UNLOCK")) {
  	*sc = SC_M_UNLOCK;
      } else if(0 == strcmp(method, "ACL")) {
  	*sc = SC_M_ACL;
      } else if(0 == strcmp(method, "REPORT")) {
  	*sc = SC_M_REPORT;
      } else if(0 == strcmp(method, "VERSION-CONTROL")) {
          *sc = SC_M_VERSION_CONTROL;
      } else if(0 == strcmp(method, "CHECKIN")) {
          *sc = SC_M_CHECKIN;
      } else if(0 == strcmp(method, "CHECKOUT")) {
          *sc = SC_M_CHECKOUT;
      } else if(0 == strcmp(method, "UNCHECKOUT")) {
          *sc = SC_M_UNCHECKOUT;
      } else if(0 == strcmp(method, "SEARCH")) {
          *sc = SC_M_SEARCH;
      } else {
          rc = JK_FALSE;
      }
  
      return rc;
  }
  
  static int sc_for_req_header(const char     *header_name,
                               unsigned short *sc) 
  {
      switch(header_name[0]) {
          case 'a':
              if('c' ==header_name[1] &&
                 'c' ==header_name[2] &&
                 'e' ==header_name[3] &&
                 'p' ==header_name[4] &&
                 't' ==header_name[5]) {
                  if ('-' == header_name[6]) {
                      if(!strcmp(header_name + 7, "charset")) {
                          *sc = SC_ACCEPT_CHARSET;
                      } else if(!strcmp(header_name + 7, "encoding")) {
                          *sc = SC_ACCEPT_ENCODING;
                      } else if(!strcmp(header_name + 7, "language")) {
                          *sc = SC_ACCEPT_LANGUAGE;
                      } else {
                          return JK_FALSE;
                      }
                  } else if ('\0' == header_name[6]) {
                      *sc = SC_ACCEPT;
                  } else {
                      return JK_FALSE;
                  }
              } else if (!strcmp(header_name, "authorization")) {
                  *sc = SC_AUTHORIZATION;
              } else {
                  return JK_FALSE;
              }
          break;
  
          case 'c':
              if(!strcmp(header_name, "cookie")) {
                  *sc = SC_COOKIE;
              } else if(!strcmp(header_name, "connection")) {
                  *sc = SC_CONNECTION;
              } else if(!strcmp(header_name, "content-type")) {
                  *sc = SC_CONTENT_TYPE;
              } else if(!strcmp(header_name, "content-length")) {
                  *sc = SC_CONTENT_LENGTH;
              } else if(!strcmp(header_name, "cookie2")) {
                  *sc = SC_COOKIE2;
              } else {
                  return JK_FALSE;
              }
          break;
  
          case 'h':
              if(!strcmp(header_name, "host")) {
                  *sc = SC_HOST;
              } else {
                  return JK_FALSE;
              }
          break;
  
          case 'p':
              if(!strcmp(header_name, "pragma")) {
                  *sc = SC_PRAGMA;
              } else {
                  return JK_FALSE;
              }
          break;
  
          case 'r':
              if(!strcmp(header_name, "referer")) {
                  *sc = SC_REFERER;
              } else {
                  return JK_FALSE;
              }
          break;
  
          case 'u':
              if(!strcmp(header_name, "user-agent")) {
                  *sc = SC_USER_AGENT;
              } else {
                  return JK_FALSE;
              }
          break;
  
          default:
              return JK_FALSE;
      }
  
      return JK_TRUE;
  }
  
  
  /*
   * Message structure
   *
   *
  AJPV13_REQUEST/AJPV14_REQUEST=
      request_prefix (1) (byte)
      method         (byte)
      protocol       (string)
      req_uri        (string)
      remote_addr    (string)
      remote_host    (string)
      server_name    (string)
      server_port    (short)
      is_ssl         (boolean)
      num_headers    (short)
      num_headers*(req_header_name header_value)
  
      ?context       (byte)(string)
      ?servlet_path  (byte)(string)
      ?remote_user   (byte)(string)
      ?auth_type     (byte)(string)
      ?query_string  (byte)(string)
      ?jvm_route     (byte)(string)
      ?ssl_cert      (byte)(string)
      ?ssl_cipher    (byte)(string)
      ?ssl_session   (byte)(string)
      ?ssl_key_size  (byte)(int)		via JkOptions +ForwardKeySize
      request_terminator (byte)
      ?body          content_length*(var binary)
  
   */
  
  static int ajp_marshal_into_msgb(jk_msg_buf_t    *msg,
                                   jk_ws_service_t *s,
                                   jk_logger_t     *l,
  					        	 ajp_endpoint_t  *ae)
  {
      unsigned char method;
      unsigned i;
  
      jk_log(l, JK_LOG_DEBUG, "Into ajp_marshal_into_msgb\n");
  
      if (!sc_for_req_method(s->method, &method)) { 
          jk_log(l, JK_LOG_ERROR, "Error ajp_marshal_into_msgb - No such method %s\n", s->method);
          return JK_FALSE;
      }
  
      if (jk_b_append_byte(msg, JK_AJP13_FORWARD_REQUEST)  ||
          jk_b_append_byte(msg, method)               ||
          jk_b_append_string(msg, s->protocol)        ||
          jk_b_append_string(msg, s->req_uri)         ||
          jk_b_append_string(msg, s->remote_addr)     ||
          jk_b_append_string(msg, s->remote_host)     ||
          jk_b_append_string(msg, s->server_name)     ||
          jk_b_append_int(msg, (unsigned short)s->server_port) ||
          jk_b_append_byte(msg, (unsigned char)(s->is_ssl)) ||
          jk_b_append_int(msg, (unsigned short)(s->num_headers))) {
  
          jk_log(l, JK_LOG_ERROR, "Error ajp_marshal_into_msgb - Error appending the message begining\n");
          return JK_FALSE;
      }
  
      for (i = 0 ; i < s->num_headers ; i++) {
          unsigned short sc;
  
          if (sc_for_req_header(s->headers_names[i], &sc)) {
              if (jk_b_append_int(msg, sc)) {
                  jk_log(l, JK_LOG_ERROR, "Error ajp_marshal_into_msgb - Error appending the header name\n");
                  return JK_FALSE;
              }
          } else {
              if (jk_b_append_string(msg, s->headers_names[i])) {
                  jk_log(l, JK_LOG_ERROR, "Error ajp_marshal_into_msgb - Error appending the header name\n");
                  return JK_FALSE;
              }
          }
          
          if (jk_b_append_string(msg, s->headers_values[i])) {
              jk_log(l, JK_LOG_ERROR, "Error ajp_marshal_into_msgb - Error appending the header value\n");
              return JK_FALSE;
          }
      }
  
      if (s->remote_user) {
          if (jk_b_append_byte(msg, SC_A_REMOTE_USER) ||
              jk_b_append_string(msg, s->remote_user)) {
              jk_log(l, JK_LOG_ERROR, "Error ajp_marshal_into_msgb - Error appending the remote user\n");
              return JK_FALSE;
          }
      }
      if (s->auth_type) {
          if (jk_b_append_byte(msg, SC_A_AUTH_TYPE) ||
              jk_b_append_string(msg, s->auth_type)) {
              jk_log(l, JK_LOG_ERROR, "Error ajp_marshal_into_msgb - Error appending the auth type\n");
              return JK_FALSE;
          }
      }
      if (s->query_string) {
          if (jk_b_append_byte(msg, SC_A_QUERY_STRING) ||
              jk_b_append_string(msg, s->query_string)) {
              jk_log(l, JK_LOG_ERROR, "Error ajp_marshal_into_msgb - Error appending the query string\n");
              return JK_FALSE;
          }
      }
      if (s->jvm_route) {
          if (jk_b_append_byte(msg, SC_A_JVM_ROUTE) ||
              jk_b_append_string(msg, s->jvm_route)) {
              jk_log(l, JK_LOG_ERROR, "Error ajp_marshal_into_msgb - Error appending the jvm route\n");
              return JK_FALSE;
          }
      }
      if (s->ssl_cert_len) {
          if (jk_b_append_byte(msg, SC_A_SSL_CERT) ||
              jk_b_append_string(msg, s->ssl_cert)) {
              jk_log(l, JK_LOG_ERROR, "Error ajp_marshal_into_msgb - Error appending the SSL certificates\n");
              return JK_FALSE;
          }
      }
  
      if (s->ssl_cipher) {
          if (jk_b_append_byte(msg, SC_A_SSL_CIPHER) ||
              jk_b_append_string(msg, s->ssl_cipher)) {
              jk_log(l, JK_LOG_ERROR, "Error ajp_marshal_into_msgb - Error appending the SSL ciphers\n");
              return JK_FALSE;
          }
      }
      if (s->ssl_session) {
          if (jk_b_append_byte(msg, SC_A_SSL_SESSION) ||
              jk_b_append_string(msg, s->ssl_session)) {
              jk_log(l, JK_LOG_ERROR, "Error ajp_marshal_into_msgb - Error appending the SSL session\n");
              return JK_FALSE;
          }
      }
  
      /*
       * ssl_key_size is required by Servlet 2.3 API
       * added support only in ajp14 mode
       * JFC removed: ae->proto == AJP14_PROTO
       */
      if (s->ssl_key_size != -1) {
          if (jk_b_append_byte(msg, SC_A_SSL_KEY_SIZE) ||
              jk_b_append_int(msg, (unsigned short) s->ssl_key_size)) {
              jk_log(l, JK_LOG_ERROR, "Error ajp_marshal_into_msgb - Error appending the SSL key size\n");
              return JK_FALSE;
          }
      }
  
  
      if (s->num_attributes > 0) {
          for (i = 0 ; i < s->num_attributes ; i++) {
              if (jk_b_append_byte(msg, SC_A_REQ_ATTRIBUTE)       ||
                  jk_b_append_string(msg, s->attributes_names[i]) ||
                  jk_b_append_string(msg, s->attributes_values[i])) {
                  jk_log(l, JK_LOG_ERROR, "Error ajp_marshal_into_msgb - Error appending attribute %s=%s\n",
                        s->attributes_names[i], s->attributes_values[i]);
                  return JK_FALSE;
              }
          }
      }
  
      if (jk_b_append_byte(msg, SC_A_ARE_DONE)) {
          jk_log(l, JK_LOG_ERROR, "Error ajp_marshal_into_msgb - Error appending the message end\n");
          return JK_FALSE;
      }
      
      jk_log(l, JK_LOG_DEBUG, "ajp_marshal_into_msgb - Done\n");
      return JK_TRUE;
  }
  
  int ajp13_marshal_shutdown_into_msgb(jk_msg_buf_t *msg,
                                       jk_pool_t *p,
                                       jk_logger_t *l)
  {
      jk_log(l, JK_LOG_DEBUG, "Into ajp13_marshal_shutdown_into_msgb\n");
      
      /* To be on the safe side */
      jk_b_reset(msg);
  
      /*
       * Just a single byte with s/d command.
       */
      if (jk_b_append_byte(msg, JK_AJP13_SHUTDOWN)) {
          jk_log(l, JK_LOG_ERROR, "ajp13_marshal_shutdown_into_msgb: "
                 "Error appending shutdown message\n");
          return JK_FALSE;
      }
  
      return JK_TRUE;
  }
  
  
  /*
  AJPV13_RESPONSE/AJPV14_RESPONSE:=
      response_prefix (2)
      status          (short)
      status_msg      (short)
      num_headers     (short)
      num_headers*(res_header_name header_value)
      *body_chunk
      terminator      boolean <! -- recycle connection or not  -->
  
  req_header_name := 
      sc_req_header_name | (string)
  
  res_header_name := 
      sc_res_header_name | (string)
  
  header_value :=
      (string)
  
  body_chunk :=
      length  (short)
      body    length*(var binary)
  
   */
  
  
  static int ajp_unmarshal_response(jk_msg_buf_t   *msg,
                                    jk_res_data_t  *d,
  						          ajp_endpoint_t *ae,
                                    jk_logger_t    *l)
  {
  	jk_pool_t * p = &ae->pool;
  
      d->status = jk_b_get_int(msg);
  
      if (!d->status) {
          jk_log(l, JK_LOG_ERROR, "Error ajp_unmarshal_response - Null status\n");
          return JK_FALSE;
      }
  
      d->msg = (char *)jk_b_get_string(msg);
      if (d->msg)
          jk_xlate_from_ascii(d->msg, strlen(d->msg));
  
      jk_log(l, JK_LOG_DEBUG, "ajp_unmarshal_response: status = %d\n", d->status);
  
      d->num_headers = jk_b_get_int(msg);
      d->header_names = d->header_values = NULL;
  
      jk_log(l, JK_LOG_DEBUG, "ajp_unmarshal_response: Number of headers is = %d\n", d->num_headers);
  
      if (d->num_headers) {
          d->header_names = jk_pool_alloc(p, sizeof(char *) * d->num_headers);
          d->header_values = jk_pool_alloc(p, sizeof(char *) * d->num_headers);
  
          if (d->header_names && d->header_values) {
              unsigned i;
              for(i = 0 ; i < d->num_headers ; i++) {
                  unsigned short name = jk_b_pget_int(msg, jk_b_get_pos(msg)) ;
                  
                  if ((name & 0XFF00) == 0XA000) {
                      jk_b_get_int(msg);
                      name = name & 0X00FF;
                      if (name <= SC_RES_HEADERS_NUM) {
                          d->header_names[i] = (char *)long_res_header_for_sc(name);
                      } else {
                          jk_log(l, JK_LOG_ERROR, "Error ajp_unmarshal_response - No such sc (%d)\n", name);
                          return JK_FALSE;
                      }
                  } else {
                      d->header_names[i] = (char *)jk_b_get_string(msg);
                      if (!d->header_names[i]) {
                          jk_log(l, JK_LOG_ERROR, "Error ajp_unmarshal_response - Null header name\n");
                          return JK_FALSE;
                      }
                      jk_xlate_from_ascii(d->header_names[i],
                                   strlen(d->header_names[i]));
  
                  }
  
                  d->header_values[i] = (char *)jk_b_get_string(msg);
                  if (!d->header_values[i]) {
                      jk_log(l, JK_LOG_ERROR, "Error ajp_unmarshal_response - Null header value\n");
                      return JK_FALSE;
                  }
  
                  jk_xlate_from_ascii(d->header_values[i],
                               strlen(d->header_values[i]));
  
                  jk_log(l, JK_LOG_DEBUG, "ajp_unmarshal_response: Header[%d] [%s] = [%s]\n", 
                         i,
                         d->header_names[i],
                         d->header_values[i]);
              }
          }
      }
  
      return JK_TRUE;
  }
  
  
  /*
   * Reset the endpoint (clean buf)
   */
  
  static void ajp_reset_endpoint(ajp_endpoint_t *ae)
  {
      ae->reuse = JK_FALSE;
      jk_reset_pool(&(ae->pool));
  }
  
  /*
   * Close the endpoint (clean buf and close socket)
   */
  
  void ajp_close_endpoint(ajp_endpoint_t *ae,
                          jk_logger_t    *l)
  {
      jk_log(l, JK_LOG_DEBUG, "In jk_endpoint_t::ajp_close_endpoint\n");
  
      ajp_reset_endpoint(ae);
      jk_close_pool(&(ae->pool));
  
  #ifdef CHANNEL
      {
  	jk_channel_t *channel=ae->worker->worker.channel;
  	int err=channel->close( channel, &ae->endpoint );
      }
  #else
      if (ae->sd > 0) { 
  	jk_close_socket(ae->sd);
  	jk_log(l, JK_LOG_DEBUG, "In jk_endpoint_t::ajp_close_endpoint, closed sd = %d\n", ae->sd);
  	ae->sd = -1; /* just to avoid twice close */
      }
  #endif
  
      free(ae);
  }
  
  #ifndef CHANNEL
  /*
   * Try to reuse a previous connection
   */
  static void ajp_reuse_connection(ajp_endpoint_t *ae,
                                   jk_logger_t    *l)
  {
      ajp_worker_t *aw = ae->worker;
      
      if (aw==NULL ) 
          return;
      if (aw->ep_cache_sz) {
          int rc;
          JK_ENTER_CS(&aw->cs, rc);
          if (rc) {
              unsigned i;
  
              for (i = 0 ; i < aw->ep_cache_sz ; i++) {
                  if (aw->ep_cache[i]) {
                      ae->sd = aw->ep_cache[i]->sd;
                      aw->ep_cache[i]->sd = -1;
                      ajp_close_endpoint(aw->ep_cache[i], l);
                      aw->ep_cache[i] = NULL;
                      break;
                   }
              }
              JK_LEAVE_CS(&aw->cs, rc);
          }
      }
  }
  #endif
  
  
  int ajp_connect_to_endpoint(ajp_endpoint_t *ae,
                              jk_logger_t    *l)
  {
      unsigned attempt;
  
      for(attempt = 0 ; attempt < ae->worker->connect_retry_attempts ; attempt++) {
  #ifdef CHANNEL
  	jk_channel_t *channel=ae->worker->worker.channel;
          int err=channel->open( channel, &ae->endpoint );
  	jk_log(l, JK_LOG_DEBUG, "ajp_connect_to_endpoint: connected %lx\n", &ae->endpoint );
  	if( err == JK_TRUE ) {
  #else
          ae->sd = jk_open_socket(&ae->worker->worker_inet_addr, JK_TRUE, l);
          if(ae->sd >= 0) {
              jk_log(l, JK_LOG_DEBUG, "In jk_endpoint_t::ajp_connect_to_endpoint, connected sd = %d\n", ae->sd);
  #endif
  	    /* Check if we must execute a logon after the physical connect */
  	    if (ae->worker->logon != NULL)
  		return (ae->worker->logon(ae, l));
  	    
  	    return JK_TRUE;
          }
      }
  
      jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::ajp_connect_to_endpoint, failed errno = %d\n", errno);
      return JK_FALSE; 
  }
  
  /*
   * Send a message to endpoint, using corresponding PROTO HEADER
   */
  
  int ajp_connection_tcp_send_message(ajp_endpoint_t *ae,
                                      jk_msg_buf_t   *msg,
                                      jk_logger_t    *l)
  {
      jk_b_end(msg, AJP13_WS_HEADER);
      jk_dump_buff(l, JK_LOG_DEBUG, "sending to ajp13", msg);
  #ifdef CHANNEL
      {
  	int err;
  	jk_channel_t *channel=ae->worker->worker.channel;
      
  	err=channel->send( channel, &ae->endpoint, 
  			   jk_b_get_buff(msg), jk_b_get_len(msg) );
  	if( err!=JK_TRUE ) {
  	    return err;
  	}
      }
  #else
      if(0 > jk_tcp_socket_sendfull(ae->sd, jk_b_get_buff(msg), jk_b_get_len(msg))) {
          return JK_FALSE;
      }
  #endif
  
      return JK_TRUE;
  }
  
  /*
   * Receive a message from endpoint, checking PROTO HEADER
   */
  
  int ajp_connection_tcp_get_message(ajp_endpoint_t *ae,
                                     jk_msg_buf_t   *msg,
                                     jk_logger_t    *l)
  {
      unsigned char head[AJP_HEADER_LEN];
      int           rc;
      int           msglen;
      unsigned int  header;
  
      if ((ae->proto != AJP13_PROTO) && (ae->proto != AJP14_PROTO)) {
  	jk_log(l, JK_LOG_ERROR, "ajp_connection_tcp_get_message:"
  	       " Can't handle unknown protocol %d\n", ae->proto);
  	return JK_FALSE;
      }
  #ifdef CHANNEL
      {
  	jk_channel_t *channel=ae->worker->worker.channel;
      
  	rc=channel->recv( channel, &ae->endpoint, 
  			     head, AJP_HEADER_LEN );
      }
  #else
      rc = jk_tcp_socket_recvfull(ae->sd, head, AJP_HEADER_LEN);
  #endif
  
      if(rc < 0) {
          jk_log(l, JK_LOG_ERROR, "ajp_connection_tcp_get_message: Error - jk_tcp_socket_recvfull failed\n");
          return JK_FALSE;
      }
  
      header = ((unsigned int)head[0] << 8) | head[1];
      
      if (header != AJP13_SW_HEADER) {
          jk_log(l, JK_LOG_ERROR, "ajp_connection_tcp_get_message:"
                 "Error - Wrong message format 0x%04x\n", header);
          return JK_FALSE;
      }
  
      msglen  = ((head[2]&0xff)<<8);
      msglen += (head[3] & 0xFF);
  
      if(msglen > jk_b_get_size(msg)) {
          jk_log(l, JK_LOG_ERROR, "ajp_connection_tcp_get_message: Error - Wrong message size\n");
          return JK_FALSE;
      }
  
      jk_b_set_len(msg, msglen);
      jk_b_set_pos(msg, 0);
  
  #ifdef CHANNEL
      {
  	jk_channel_t *channel=ae->worker->worker.channel;
      
  	rc=channel->recv( channel, &ae->endpoint, 
  			     jk_b_get_buff(msg), msglen);
      }
  #else
      rc = jk_tcp_socket_recvfull(ae->sd, jk_b_get_buff(msg), msglen);
  #endif
      if(rc < 0) {
          jk_log(l, JK_LOG_ERROR, "ajp_connection_tcp_get_message: Error - jk_tcp_socket_recvfull failed\n");
          return JK_FALSE;
      }
  
      if (ae->proto == AJP13_PROTO) 
      	jk_dump_buff(l, JK_LOG_DEBUG, "received from ajp13", msg);
      else if (ae->proto == AJP14_PROTO)
  	jk_dump_buff(l, JK_LOG_DEBUG, "received from ajp14", msg);
      
      return JK_TRUE;
  }
  
  /*
   * Read all the data from the socket.
   *
   * Socket API didn't garanty all the data will be kept in a single 
   * read, so we must loop up to all awaited data are received 
   */
  
  static int ajp_read_fully_from_server(jk_ws_service_t *s,
                                        unsigned char   *buf,
                                        unsigned         len)
  {
      unsigned rdlen = 0;
      unsigned padded_len = len;
  
      if (s->is_chunked && s->no_more_chunks) {
  	return 0;
      }
      if (s->is_chunked) {
          /* Corner case: buf must be large enough to hold next
           * chunk size (if we're on or near a chunk border).
           * Pad the length to a reasonable value, otherwise the
           * read fails and the remaining chunks are tossed.
           */
          padded_len = (len < CHUNK_BUFFER_PAD) ?
                        len : len - CHUNK_BUFFER_PAD;
      }
  
      while(rdlen < padded_len) {
          unsigned this_time = 0;
          if(!s->read(s, buf + rdlen, len - rdlen, &this_time)) {
              return -1;
          }
  
          if(0 == this_time) {
  	    if (s->is_chunked) {
  		s->no_more_chunks = 1; /* read no more */
  	    }
              break;
          }
          rdlen += this_time;
      }
  
      return (int)rdlen;
  }
  
  
  /*
   * Read data from AJP13/AJP14 protocol
   * Returns -1 on error, else number of bytes read
   */
  
  static int ajp_read_into_msg_buff(ajp_endpoint_t  *ae,
                                    jk_ws_service_t *r,
                                    jk_msg_buf_t    *msg,
                                    unsigned         len,
                                    jk_logger_t     *l)
  {
      unsigned char *read_buf = jk_b_get_buff(msg);
  
      jk_b_reset(msg);
  
      read_buf += AJP_HEADER_LEN;    /* leave some space for the buffer headers */
      read_buf += AJP_HEADER_SZ_LEN; /* leave some space for the read length */
  
      /* Pick the max size since we don't know the content_length */
      if (r->is_chunked && len == 0) {
  	len = AJP13_MAX_SEND_BODY_SZ;
      }
  
      if ((len = ajp_read_fully_from_server(r, read_buf, len)) < 0) {
          jk_log(l, JK_LOG_ERROR, "ajp_read_into_msg_buff: Error - ajp_read_fully_from_server failed\n");
          return -1;
      }
  
      if (!r->is_chunked) {
  	ae->left_bytes_to_send -= len;
      }
  
      if (len > 0) {
  	/* Recipient recognizes empty packet as end of stream, not
  	   an empty body packet */
          if(0 != jk_b_append_int(msg, (unsigned short)len)) {
              jk_log(l, JK_LOG_ERROR, 
                     "read_into_msg_buff: Error - jk_b_append_int failed\n");
              return -1;
  	}
      }
  
      jk_b_set_len(msg, jk_b_get_len(msg) + len);
  
      return len;
  }
  
  
  /*
   * send request to Tomcat via Ajp13
   * - first try to find reuseable socket
   * - if no one available, try to connect
   * - send request, but send must be see as asynchronous,
   *   since send() call will return noerror about 95% of time
   *   Hopefully we'll get more information on next read.
   * 
   * nb: reqmsg is the original request msg buffer
   *     repmsg is the reply msg buffer which could be scratched
   */
  static int ajp_send_request(jk_endpoint_t *e,
  			    jk_ws_service_t *s,
  			    jk_logger_t *l,
  			    ajp_endpoint_t *ae,
  			    ajp_operation_t *op)
  {
      int err=JK_TRUE;
      
      /* Up to now, we can recover */
      op->recoverable = JK_TRUE;
  
      /*
       * First try to reuse open connections...
       */
  #ifdef CHANNEL
      {
        jk_channel_t *channel=ae->worker->worker.channel;
        err=ajp_connection_tcp_send_message(ae, op->request, l);
        if( err != JK_TRUE ) {
            jk_log(l, JK_LOG_ERROR, "Error sending request, close endpoint\n");
            channel->close( channel, &ae->endpoint );
        }
      }
  #else
      while ((ae->sd > 0) && ! ajp_connection_tcp_send_message(ae, op->request, l)) {
  	jk_log(l, JK_LOG_ERROR, "Error sending request try another pooled connection\n");
  	jk_close_socket(ae->sd);
  	ae->sd = -1;
  	ajp_reuse_connection(ae, l);
      }
      if (ae->sd < 0) 
  	err=JK_FALSE;
  #endif
  
      /*
       * If we failed to reuse a connection, try to reconnect.
       */
      if( err != JK_TRUE ) {
          err=ajp_connect_to_endpoint(ae, l);
  	if ( err != JK_TRUE) {
  	    jk_log(l, JK_LOG_ERROR, "Error connecting to the Tomcat process.\n");
  	    return JK_FALSE;
          }
          /*
           * After we are connected, each error that we are going to
           * have is probably unrecoverable
           */
          err=ajp_connection_tcp_send_message(ae, op->request, l);
          if (err != JK_TRUE) {
              jk_log(l, JK_LOG_ERROR, "Error sending request on a fresh connection\n");
              return JK_FALSE;
          }
      }
      
      /*
       * From now on an error means that we have an internal server error
       * or Tomcat crashed. In any case we cannot recover this.
       */
      
      jk_log(l, JK_LOG_DEBUG, "ajp_send_request 2: request body to send %d - request body to resend %d\n", 
  	   ae->left_bytes_to_send, jk_b_get_len(op->reply) - AJP_HEADER_LEN);
      
      /*
       * POST recovery job is done here.
       * It's not very fine to have posted data in reply but that's the only easy
       * way to do that for now. Sharing the reply is really a bad solution but
       * it will works for POST DATA less than 8k.
       * We send here the first part of data which was sent previously to the
       * remote Tomcat
       */
      if (jk_b_get_len(op->post) > AJP_HEADER_LEN) {
          err=ajp_connection_tcp_send_message(ae, op->post, l);
  	if(err != JK_TRUE) {
  	    jk_log(l, JK_LOG_ERROR, "Error resending request body\n");
  	    return JK_FALSE;
  	}
      } else {
  	/* We never sent any POST data and we check it we have to send at
  	 * least of block of data (max 8k). These data will be kept in reply
  	 * for resend if the remote Tomcat is down, a fact we will learn only
  	 * doing a read (not yet) 
  	 */
  	if (s->is_chunked || ae->left_bytes_to_send > 0) {
  	    unsigned len = ae->left_bytes_to_send;
  	    if (len > AJP13_MAX_SEND_BODY_SZ) 
  		len = AJP13_MAX_SEND_BODY_SZ;
              len = ajp_read_into_msg_buff(ae, s, op->post, len, l);
  	    if (len < 0) {
  		/* the browser stop sending data, no need to recover */
  		op->recoverable = JK_FALSE;
  		return JK_FALSE;
  	    }
  	    s->content_read = len;
              err=ajp_connection_tcp_send_message(ae, op->post, l);
  	    if (err!=JK_TRUE) {
  		jk_log(l, JK_LOG_ERROR, "Error sending request body\n");
  		return JK_FALSE;
  	    }  
  	}
      }
      return (JK_TRUE);
  }
  
  /*
   * What to do with incoming data (dispatcher)
   */
  
  static int ajp_process_callback(jk_msg_buf_t *msg, 
                                  jk_msg_buf_t *pmsg,
                                  ajp_endpoint_t *ae,
                                  jk_ws_service_t *r, 
                                  jk_logger_t *l) 
  {
      int code = (int)jk_b_get_byte(msg);
  
      switch(code) {
          case JK_AJP13_SEND_HEADERS:
              {
                  jk_res_data_t res;
                  if (!ajp_unmarshal_response(msg, &res, ae, l)) {
                      jk_log(l, JK_LOG_ERROR, "Error ajp_process_callback - ajp_unmarshal_response failed\n");
                      return JK_AJP13_ERROR;
                  }
                  if (!r->start_response(r, 
                                         res.status, 
                                         res.msg, 
                                         (const char * const *)res.header_names,
                                         (const char * const *)res.header_values,
                                         res.num_headers)) {
                      jk_log(l, JK_LOG_ERROR, "Error ajp_process_callback - start_response failed\n");
                      return JK_CLIENT_ERROR;
                  }
              }
  	    break;
  
          case JK_AJP13_SEND_BODY_CHUNK:
              {
  	            unsigned len = (unsigned)jk_b_get_int(msg);
                  if(!r->write(r, jk_b_get_buff(msg) + jk_b_get_pos(msg), len)) {
                      jk_log(l, JK_LOG_ERROR, "Error ajp_process_callback - write failed\n");
                      return JK_CLIENT_ERROR;
                  }
              }
  	    break;
  
          case JK_AJP13_GET_BODY_CHUNK:
              {
  		unsigned len = (unsigned)jk_b_get_int(msg);
  
                  if(len > AJP13_MAX_SEND_BODY_SZ) {
                      len = AJP13_MAX_SEND_BODY_SZ;
                  }
                  if(len > ae->left_bytes_to_send) {
                      len = ae->left_bytes_to_send;
                  }
  		if(len < 0) {
  		    len = 0;
  		}
  
  		/* the right place to add file storage for upload */
  		if ((len = ajp_read_into_msg_buff(ae, r, msg, len, l)) >= 0) {
  		    r->content_read += len;
  		    return JK_AJP13_HAS_RESPONSE;
  		}                  
  
  		jk_log(l, JK_LOG_ERROR, "Error ajp_process_callback - ajp_read_into_msg_buff failed\n");
  		return JK_INTERNAL_ERROR;	    
              }
  	    break;
  
          case JK_AJP13_END_RESPONSE:
              {
                  ae->reuse = (int)jk_b_get_byte(msg);
                  
                  if((ae->reuse & 0X01) != ae->reuse) {
                      /*
                       * Strange protocol error.
                       */
                      ae->reuse = JK_FALSE;
                  }
              }
              return JK_AJP13_END_RESPONSE;
  	    break;
  
          default:
  	        jk_log(l, JK_LOG_ERROR, "Error ajp_process_callback - Invalid code: %d\n", code);
  		jk_dump_buff(l, JK_LOG_ERROR, "Message: ", msg);
  	        return JK_AJP13_ERROR;
      }
      
      return JK_AJP13_NO_RESPONSE;
  }
  
  /*
   * get replies from Tomcat via Ajp13/Ajp14
   * We will know only at read time if the remote host closed
   * the connection (half-closed state - FIN-WAIT2). In that case
   * we must close our side of the socket and abort emission.
   * We will need another connection to send the request
   * There is need of refactoring here since we mix 
   * reply reception (tomcat -> apache) and request send (apache -> tomcat)
   * and everything using the same buffer (repmsg)
   * ajp13/ajp14 is async but handling read/send this way prevent nice recovery
   * In fact if tomcat link is broken during upload (browser -> apache -> tomcat)
   * we'll loose data and we'll have to abort the whole request.
   */
  static int ajp_get_reply(jk_endpoint_t *e,
                           jk_ws_service_t *s,
                           jk_logger_t *l,
  			             ajp_endpoint_t *p,
  			             ajp_operation_t *op)
  {
  	/* Start read all reply message */
  	while(1) {
  		int rc = 0;
  
  		if(!ajp_connection_tcp_get_message(p, op->reply, l)) {
  			jk_log(l, JK_LOG_ERROR, "Error reading reply\n");
  			/* we just can't recover, unset recover flag */
  			return JK_FALSE;
  		}
  
  		rc = ajp_process_callback(op->reply, op->post, p, s, l);
  
  		/* no more data to be sent, fine we have finish here */
         		if(JK_AJP13_END_RESPONSE == rc)
          		return JK_TRUE;
          	else if(JK_AJP13_HAS_RESPONSE == rc) {
          	/* 
          	 * in upload-mode there is no second chance since
          	 * we may have allready send part of uploaded data 
          	 * to Tomcat.
          	 * In this case if Tomcat connection is broken we must 
          	 * abort request and indicate error.
          	 * A possible work-around could be to store the uploaded
          	 * data to file and replay for it
          	 */
   			op->recoverable = JK_FALSE; 
  			rc = ajp_connection_tcp_send_message(p, op->post, l);
          		if (rc < 0) {
  				jk_log(l, JK_LOG_ERROR, "Error sending request data %d\n", rc);
                 	 		return JK_FALSE;
  			}
          } else if(JK_FATAL_ERROR == rc) {
            /*
             * we won't be able to gracefully recover from this so
             * set recoverable to false and get out.
             */
              op->recoverable = JK_FALSE;
              return JK_FALSE;
          } else if(JK_CLIENT_ERROR == rc) {
                    /*
                     * Client has stop talking to us, so get out.
                     * We assume this isn't our fault, so just a normal exit.
                     * In most (all?)  cases, the ajp13_endpoint::reuse will still be
                     * false here, so this will be functionally the same as an
                     * un-recoverable error.  We just won't log it as such.
                     */
                  return JK_TRUE;
  		} else if(rc < 0) {
  			return (JK_FALSE); /* XXX error */
  		}
  	}
  }
  
  #define	JK_RETRIES 3
  
  /*
   * service is now splitted in ajp_send_request and ajp_get_reply
   * much more easier to do errors recovery
   *
   * We serve here the request, using AJP13/AJP14 (e->proto)
   *
   */
  int JK_METHOD ajp_service(jk_endpoint_t   *e, 
                  jk_ws_service_t *s,
                  jk_logger_t     *l,
                  int             *is_recoverable_error)
  {
      int i;
      int err;
      ajp_operation_t oper;
      ajp_operation_t *op = &oper;
      ajp_endpoint_t *p;
      
      jk_log(l, JK_LOG_DEBUG, "Into jk_endpoint_t::service\n");
  
      if( ( e== NULL ) || ( e->endpoint_private==NULL )
  	|| ( s == NULL ) || ! is_recoverable_error ) {
  	jk_log(l, JK_LOG_ERROR, "jk_endpoint_t::service: NULL parameters\n");
  	return JK_FALSE;
      }
  	
      p = e->endpoint_private;
      op->request = jk_b_new(&(p->pool));
      jk_b_set_buffer_size(op->request, DEF_BUFFER_SZ); 
      jk_b_reset(op->request);
      
      op->reply = jk_b_new(&(p->pool));
      jk_b_set_buffer_size(op->reply, DEF_BUFFER_SZ);
      jk_b_reset(op->reply); 
  	
      op->post = jk_b_new(&(p->pool));
      jk_b_set_buffer_size(op->post, DEF_BUFFER_SZ);
      jk_b_reset(op->post); 
      
      op->recoverable = JK_TRUE;
      op->uploadfd	 = -1;		/* not yet used, later ;) */
      
      p->left_bytes_to_send = s->content_length;
      p->reuse = JK_FALSE;
      *is_recoverable_error = JK_TRUE;
      
      /* 
       * We get here initial request (in reqmsg)
       */
      if (!ajp_marshal_into_msgb(op->request, s, l, p)) {
  	*is_recoverable_error = JK_FALSE;                
  	jk_log(l, JK_LOG_ERROR, "jk_endpoint_t::service: error marshaling\n");
  	return JK_FALSE;
      }
      
      /* 
       * JK_RETRIES could be replaced by the number of workers in
       * a load-balancing configuration 
       */
      for (i = 0; i < JK_RETRIES; i++) {
  	/*
  	 * We're using reqmsg which hold initial request
  	 * if Tomcat is stopped or restarted, we will pass reqmsg
  	 * to next valid tomcat. 
  	 */
  	err=ajp_send_request(e, s, l, p, op);
  	if (err!=JK_TRUE ) {
  	    jk_log(l, JK_LOG_ERROR, 
  		   "In jk_endpoint_t::service, ajp_send_request"
  		   "failed in send loop %d\n", i);
  	} else {
  	    /* If we have the no recoverable error, it's probably because the sender (browser)
  	     * stop sending data before the end (certainly in a big post)
  	     */
  	    if (! op->recoverable) {
  		*is_recoverable_error = JK_FALSE;
  		jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service,"
  		       "ajp_send_request failed without recovery in send loop %d\n", i);
  		return JK_FALSE;
  	    }
  	    
  	    /* Up to there we can recover */
  	    *is_recoverable_error = JK_TRUE;
  	    op->recoverable = JK_TRUE;
  	    
  	    if (ajp_get_reply(e, s, l, p, op))
  		return (JK_TRUE);
  	    
  	    /* if we can't get reply, check if no recover flag was set 
  	     * if is_recoverable_error is cleared, we have started received 
  	     * upload data and we must consider that operation is no more recoverable
  	     */
  	    if (! op->recoverable) {
  		*is_recoverable_error = JK_FALSE;
  		jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service,"
  		       "ajp_get_reply failed without recovery in send loop %d\n", i);
  		return JK_FALSE;
  	    }
  	    
  	    jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service,"
  		   "ajp_get_reply failed in send loop %d\n", i);
  	}
  	/* Try again to connect */
  #ifdef CHANNEL
  	{
  	    jk_channel_t *channel=p->worker->worker.channel;
  	    
  	    jk_log(l, JK_LOG_ERROR, "Error sending request, reconnect\n");
  	    err=channel->close( channel, &p->endpoint );
  	    err=channel->open( channel, &p->endpoint );
  	    if( err != JK_TRUE ) {
  		jk_log(l, JK_LOG_ERROR, "Reconnect failed\n");
  		return err;
  	    }
  	}
  #else
  	jk_log(l, JK_LOG_ERROR, "Error sending request try another pooled connection\n");
  	jk_close_socket(p->sd);
  	p->sd = -1;
  	ajp_reuse_connection(p, l);
  #endif
      }
      
      return JK_FALSE;
  }
  
  /*
   * Validate the worker (ajp13/ajp14)
   */
  int ajp_validate(jk_worker_t *pThis,
                   jk_map_t    *props,
                   jk_workerEnv_t *we,
                   jk_logger_t *l,
  		 int proto)
  {
      int    port;
      char * host;
      int err;
      ajp_worker_t *p = pThis->worker_private;
  
      jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::validate\n");
  
      if( ( pThis==NULL )  || ( pThis->worker_private==NULL ) ) 
  	return JK_FALSE;
  
      if (proto == AJP13_PROTO) {
  	port = AJP13_DEF_PORT;
  	host = AJP13_DEF_HOST;
      } else if (proto == AJP14_PROTO) {
  	port = AJP14_DEF_PORT;
  	host = AJP14_DEF_HOST;
      } else {
  	jk_log(l, JK_LOG_DEBUG, "In jk_worker_t::validate unknown protocol %d\n", proto);
  	return JK_FALSE;
      } 
  #ifdef CHANNEL
      if( pThis->channel == NULL ) {
  	/* Create a default channel */
  	jk_env_t *env= we->env;
  
  	jk_env_objectFactory_t fac = 
  	    (jk_env_objectFactory_t)env->getFactory(env, "channel", "socket" );
  	jk_log( l, JK_LOG_DEBUG, "Got socket channel factory \n");
  
  	err=fac( env, (void **)&pThis->channel, "channel", "socket" );
  	if( err != JK_TRUE ) {
  	    jk_log(l, JK_LOG_ERROR, "Error creating socket factory\n");
  	    return err;
  	}
  	jk_log(l, JK_LOG_ERROR, "Got channel %lx\n", pThis->channel);
      }
      
      pThis->channel->setProperty( pThis->channel, "defaultPort", "8007" );
  
      err=pThis->channel->init( pThis->channel, props, p->name, pThis, l );
      if( err != JK_TRUE ) {
  	jk_log(l, JK_LOG_ERROR, "In jk_worker_t::validate, resolve failed\n");
  	return err;
      }
      
      return JK_TRUE;
  #else    
      if (pThis->worker_private) {
          port = jk_get_worker_port(props, p->name, port);
          host = jk_get_worker_host(props, p->name, host);
  
          jk_log(l, JK_LOG_DEBUG, "In jk_worker_t::validate for worker %s contact is %s:%d\n", p->name, host, port);
  
          if(port > 1024 && host) {
              if(jk_resolve(host, (short)port, &p->worker_inet_addr)) {
                  return JK_TRUE;
              }
              jk_log(l, JK_LOG_ERROR, "In jk_worker_t::validate, resolve failed\n");
          }
          jk_log(l, JK_LOG_ERROR, "In jk_worker_t::validate, Error %s %d\n", host, port);
      } else {
          jk_log(l, JK_LOG_ERROR, "In jk_worker_t::validate, NULL parameters\n");
      }
      return JK_FALSE;
  #endif
  }
  
  
  int ajp_init(jk_worker_t *pThis,
               jk_map_t    *props,
               jk_workerEnv_t *we,
               jk_logger_t *l,
               int          proto)
  {
  	int cache;
  	
      /*
       * start the connection cache
       */
      jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::init\n");
  
      if (proto == AJP13_PROTO) {
          cache = AJP13_DEF_CACHE_SZ;
      }
      else if (proto == AJP14_PROTO) {
          cache = AJP13_DEF_CACHE_SZ;
      }
      else {
          jk_log(l, JK_LOG_DEBUG, "In jk_worker_t::validate unknown protocol %d\n", proto);
          return JK_FALSE;
      }
  
      if (pThis && pThis->worker_private) {
          ajp_worker_t *p = pThis->worker_private;
          int cache_sz = jk_get_worker_cache_size(props, p->name, cache);
          if (cache_sz > 0) {
              p->ep_cache = (ajp_endpoint_t **)malloc(sizeof(ajp_endpoint_t *) * cache_sz);
              if(p->ep_cache) {
                  int i;
                  p->ep_cache_sz = cache_sz;
                  for(i = 0 ; i < cache_sz ; i++) {
                      p->ep_cache[i] = NULL;
                  }
                  JK_INIT_CS(&(p->cs), i);
                  if (i) {
                      return JK_TRUE;
                  }
              }
          }
      } else {
          jk_log(l, JK_LOG_ERROR, "In jk_worker_t::init, NULL parameters\n");
      }
  
      return JK_FALSE;
  }
  
  int ajp_destroy(jk_worker_t **pThis,
                  jk_logger_t *l,
  				int          proto)
  {
      jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::destroy\n");
  
      if (pThis && *pThis && (*pThis)->worker_private) {
          ajp_worker_t *aw = (*pThis)->worker_private;
  
         	free(aw->name);
  
  		jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::destroy up to %d endpoint to close\n", aw->ep_cache_sz);
  
          if(aw->ep_cache_sz) {
              unsigned i;
              for(i = 0 ; i < aw->ep_cache_sz ; i++) {
                  if(aw->ep_cache[i]) {
                      ajp_close_endpoint(aw->ep_cache[i], l);
                  }
              }
              free(aw->ep_cache);
              JK_DELETE_CS(&(aw->cs), i);
          }
  
  		if (aw->login) {
  			free(aw->login);
  			aw->login = NULL;
  		}
  
          free(aw);
          return JK_TRUE;
      }
  
      jk_log(l, JK_LOG_ERROR, "In jk_worker_t::destroy, NULL parameters\n");
      return JK_FALSE;
  }
  
  int JK_METHOD ajp_done(jk_endpoint_t **e,
                         jk_logger_t    *l)
  {
      jk_log(l, JK_LOG_DEBUG, "Into jk_endpoint_t::done\n");
  
      if (e && *e && (*e)->endpoint_private) {
          ajp_endpoint_t *p = (*e)->endpoint_private;
          int reuse_ep = p->reuse;
  
          ajp_reset_endpoint(p);
  
          if(reuse_ep) {
              ajp_worker_t *w = p->worker;
              if(w->ep_cache_sz) {
                  int rc;
                  JK_ENTER_CS(&w->cs, rc);
                  if(rc) {
                      unsigned i;
  
                      for(i = 0 ; i < w->ep_cache_sz ; i++) {
                          if(!w->ep_cache[i]) {
                              w->ep_cache[i] = p;
                              break;
                          }
                      }
                      JK_LEAVE_CS(&w->cs, rc);
                      if(i < w->ep_cache_sz) {
  			jk_log(l, JK_LOG_DEBUG, "Return endpoint to pool\n");
                          return JK_TRUE;
                      }
                  }
              }
          }
  
          ajp_close_endpoint(p, l);
          *e = NULL;
  
          return JK_TRUE;
      }
  
      jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::done, NULL parameters\n");
      return JK_FALSE;
  }
  
  int ajp_get_endpoint(jk_worker_t    *pThis,
                       jk_endpoint_t **je,
                       jk_logger_t    *l,
  		     int			 proto)
  {
      jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::get_endpoint\n");
  
      if (pThis && pThis->worker_private && je) {
          ajp_worker_t   *aw = pThis->worker_private;
          ajp_endpoint_t *ae = NULL;
  
          if (aw->ep_cache_sz) {
              int rc;
              JK_ENTER_CS(&aw->cs, rc);
              if (rc) {
                  unsigned i;
      
                  for (i = 0 ; i < aw->ep_cache_sz ; i++) {
                      if (aw->ep_cache[i]) {
                          ae = aw->ep_cache[i];
                          aw->ep_cache[i] = NULL;
                          break;
                      }
                  }
                  JK_LEAVE_CS(&aw->cs, rc);
                  if (ae) {
  		    jk_log(l, JK_LOG_DEBUG, "Reusing endpoint\n");
                      *je = &ae->endpoint;
                      return JK_TRUE;
                  }
              }
          }
  
          ae = (ajp_endpoint_t *)malloc(sizeof(ajp_endpoint_t));
          if (ae) {
  #ifndef CHANNEL
              ae->sd = -1;
  #endif
              ae->reuse = JK_FALSE;
              jk_open_pool(&ae->pool, ae->buf, sizeof(ae->buf));
              ae->worker = pThis->worker_private;
              ae->endpoint.endpoint_private = ae;
  	    ae->proto = proto;
  	    ae->proto = proto;
  	    ae->endpoint.channelData = NULL;
              ae->endpoint.service = ajp_service;
              ae->endpoint.done = ajp_done;
              *je = &ae->endpoint;
              return JK_TRUE;
          }
          jk_log(l, JK_LOG_ERROR, "In jk_worker_t::get_endpoint, malloc failed\n");
      } else {
          jk_log(l, JK_LOG_ERROR, "In jk_worker_t::get_endpoint, NULL parameters\n");
      }
  
      return JK_FALSE;
  }
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/common/jk_channel_socket.c
  
  Index: jk_channel_socket.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 The Apache Software License,  Version 1.1                 *
   *                                                                           *
   *          Copyright (c) 1999-2001 The Apache Software Foundation.          *
   *                           All rights reserved.                            *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * Redistribution and use in source and binary forms,  with or without modi- *
   * fication, are permitted provided that the following conditions are met:   *
   *                                                                           *
   * 1. Redistributions of source code  must retain the above copyright notice *
   *    notice, this list of conditions and the following disclaimer.          *
   *                                                                           *
   * 2. Redistributions  in binary  form  must  reproduce the  above copyright *
   *    notice,  this list of conditions  and the following  disclaimer in the *
   *    documentation and/or other materials provided with the distribution.   *
   *                                                                           *
   * 3. The end-user documentation  included with the redistribution,  if any, *
   *    must include the following acknowlegement:                             *
   *                                                                           *
   *       "This product includes  software developed  by the Apache  Software *
   *        Foundation <http://www.apache.org/>."                              *
   *                                                                           *
   *    Alternately, this acknowlegement may appear in the software itself, if *
   *    and wherever such third-party acknowlegements normally appear.         *
   *                                                                           *
   * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software     *
   *    Foundation"  must not be used  to endorse or promote  products derived *
   *    from this  software without  prior  written  permission.  For  written *
   *    permission, please contact <apache@apache.org>.                        *
   *                                                                           *
   * 5. Products derived from this software may not be called "Apache" nor may *
   *    "Apache" appear in their names without prior written permission of the *
   *    Apache Software Foundation.                                            *
   *                                                                           *
   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
   * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY *
   * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL *
   * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY *
   * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL *
   * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS *
   * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) *
   * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT, *
   * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
   * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE *
   * POSSIBILITY OF SUCH DAMAGE.                                               *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * This software  consists of voluntary  contributions made  by many indivi- *
   * duals on behalf of the  Apache Software Foundation.  For more information *
   * on the Apache Software Foundation, please see <http://www.apache.org/>.   *
   *                                                                           *
   * ========================================================================= */
  
  /**
   * Channel using 'plain' TCP sockets. Based on jk_sockbuf. Will be replaced by
   * an APR-based mechanism.
   * 
   * Properties:
   *  - host
   *  - port
   *  - ndelay
   *
   *
   * @author:  Gal Shachor <shachor@il.ibm.com>                           
   * @author: Costin Manolache
   */
  
  #include "jk_map.h"
  #include "jk_env.h"
  #include "jk_channel.h"
  #include "jk_global.h"
  #include "jk_util.h"
  
  #include <string.h>
  
  #ifndef WIN32
  	#define closesocket			close
  #endif
  
  /** Information specific for the socket channel
   */
  struct jk_channel_socket_private {
      int ndelay;
      struct sockaddr_in addr;    
      char *host;
      short port;
  };
  
  /** Informations for each connection
   */
  typedef struct jk_channel_socket_data {
      int sock;
  } jk_channel_socket_data_t;
  
  typedef struct jk_channel_socket_private jk_channel_socket_private_t;
  
  /*
    We use the _privateInt field directly. Long term we can define our own
    jk_channel_socket_t structure and use the _private field, etc - but we 
    just need to store an int.
  
    XXX We could also use properties or 'notes'
  */
  
  int JK_METHOD jk_channel_socket_factory(jk_env_t *env, void **result,
  					char *type, char *name);
  static int JK_METHOD jk_channel_socket_resolve(char *host, short port,
  				     struct sockaddr_in *rc);
  
  static int JK_METHOD jk_channel_socket_getProperty(jk_channel_t *_this, 
  					 char *name, char **value)
  {
      return JK_FALSE;
  }
  
  static int JK_METHOD jk_channel_socket_setProperty(jk_channel_t *_this, 
                                                     char *name, char *value)
  {
      jk_channel_socket_private_t *socketInfo=
  	(jk_channel_socket_private_t *)(_this->_privatePtr);
  
      if( strcmp( "host", name ) != 0 ) {
  	socketInfo->host=value;
      } else if( strcmp( "defaultPort", name ) != 0 ) {
      } else if( strcmp( "port", name ) != 0 ) {
      } else {
  	return JK_FALSE;
      }
      return JK_TRUE;
  }
  
  /** resolve the host IP ( jk_resolve ) and initialize the channel.
   */
  static int JK_METHOD jk_channel_socket_init(jk_channel_t *_this, 
                                              jk_map_t *props,
                                              char *worker_name, 
                                              jk_worker_t *worker, 
                                              jk_logger_t *l )
  {
      int err=jk_log(l, JK_LOG_DEBUG, "Into jk_channel_socket_init\n");
      jk_channel_socket_private_t *socketInfo=
  	(jk_channel_socket_private_t *)(_this->_privatePtr);
  
      char *host=socketInfo->host;
      short port=socketInfo->port;
      struct sockaddr_in *rc=&socketInfo->addr;
  
      port = jk_get_worker_port(props, worker_name, port);
      host = jk_get_worker_host(props, worker_name, host);
  
      _this->worker=worker;
      _this->logger=l;
      _this->properties=props;
      
      err=jk_channel_socket_resolve( host, port, rc );
      if( err!= JK_TRUE ) {
  	jk_log(l, JK_LOG_ERROR, "jk_channel_socket_init: "
  	       "can't resolve %s:%d errno=%d\n", host, port, errno );
      }
      jk_log(l, JK_LOG_DEBUG, "jk_channel_socket_init: ok "
  	   " %s:%d\n", host, port );
  
      return err;
  }
  
  /** private: resolve the address on init
   */
  static int JK_METHOD jk_channel_socket_resolve(char *host, short port,
                                                 struct sockaddr_in *rc)
  {
      int x;
      u_long laddr;
      
      rc->sin_port   = htons((short)port);
      rc->sin_family = AF_INET;
  
      /* Check if we only have digits in the string */
      for(x = 0 ; '\0' != host[x] ; x++) {
          if(!isdigit(host[x]) && host[x] != '.') {
              break;
          }
      }
  
      if(host[x] != '\0') {
          /* If we found also characters we use gethostbyname()*/
          struct hostent *hoste = gethostbyname(host);
          if(!hoste) {
              return JK_FALSE;
          }
  
          laddr = ((struct in_addr *)hoste->h_addr_list[0])->s_addr;
      } else {
          /* If we found only digits we use inet_addr() */
          laddr = inet_addr(host);        
      }
      memcpy(&(rc->sin_addr), &laddr , sizeof(laddr));
  
      return JK_TRUE;
  }
  
  /** connect to Tomcat (jk_open_socket)
   */
  static int JK_METHOD jk_channel_socket_open(jk_channel_t *_this,
                                              jk_endpoint_t *endpoint)
  {
      jk_logger_t *l=_this->logger;
      int err=jk_log(l, JK_LOG_DEBUG, "Into jk_channel_socket_open\n");
      jk_channel_socket_private_t *socketInfo=
  	(jk_channel_socket_private_t *)(_this->_privatePtr);
  
      struct sockaddr_in *addr=&socketInfo->addr;
      int ndelay=socketInfo->ndelay;
  
      int sock;
  
      sock = socket(AF_INET, SOCK_STREAM, 0);
      if(sock > -1) {
          int ret;
          /* Tries to connect to JServ (continues trying while error is EINTR) */
          do {
              jk_log(l, JK_LOG_DEBUG, "jk_open_socket, try to connect socket = %d\n", sock);
              ret = connect(sock,
                            (struct sockaddr *)addr,
                            sizeof(struct sockaddr_in));
  #ifdef WIN32
              if(SOCKET_ERROR == ret) { 
                  errno = WSAGetLastError() - WSABASEERR;
              }
  #endif /* WIN32 */
              jk_log(l, JK_LOG_DEBUG, "jk_open_socket, after connect ret = %d\n", ret);
          } while (-1 == ret && EINTR == errno);
  
          /* Check if we connected */
          if(0 == ret) {
              if(ndelay) {
                  int set = 1;
  
                  jk_log(l, JK_LOG_DEBUG, "jk_open_socket, set TCP_NODELAY to on\n");
                  setsockopt(sock, 
                             IPPROTO_TCP, 
                             TCP_NODELAY, 
                             (char *)&set, 
                             sizeof(set));
              }   
  
              jk_log(l, JK_LOG_DEBUG, "jk_open_socket, return, sd = %d\n", sock);
  	    {
  		jk_channel_socket_data_t *sd=endpoint->channelData;
  		if( sd==NULL ) {
  		    sd=(jk_channel_socket_data_t *)
  			malloc( sizeof( jk_channel_socket_data_t ));
  		    endpoint->channelData=sd;
  		}
  		sd->sock=sock;
  	    }
              return JK_TRUE;
          }   
          jk_close_socket(sock);
      } else {
  #ifdef WIN32
          errno = WSAGetLastError() - WSABASEERR;
  #endif /* WIN32 */
      }    
  
      jk_log(l, JK_LOG_ERROR, "jk_open_socket, connect() failed errno = %d %s\n",
  	   errno, strerror( errno ) ); 
  
      return -1;
  }
  
  
  /** close the socket  ( was: jk_close_socket )
  */
  int JK_METHOD jk_channel_socket_close(jk_channel_t *_this,
                                        jk_endpoint_t *endpoint)
  {
      int sd;
      jk_channel_socket_data_t *chD=endpoint->channelData;
      if( chD==NULL ) 
  	return JK_FALSE;
      sd=chD->sock;
  
  #ifdef WIN32
      if(INVALID_SOCKET  != sd) {
          return closesocket(sd) ? JK_FALSE : JK_TRUE;; 
      }
  #else 
      if(-1 != sd) {
          return close(sd);
      }
  #endif
      return JK_FALSE;
  }
  
  /** send a long message
   * @param sd  opened socket.
   * @param b   buffer containing the data.
   * @param len length to send.
   * @return    -2: send returned 0 ? what this that ?
   *            -3: send failed.
   *            >0: total size send.
   * @bug       this fails on Unixes if len is too big for the underlying
   *             protocol.
   * @was: jk_tcp_socket_sendfull
   */
  static int JK_METHOD jk_channel_socket_send(jk_channel_t *_this,
  				  jk_endpoint_t *endpoint,
  				  char *b,
                                    int len) 
  {
      int sd;
      int  sent=0;
  
      jk_channel_socket_data_t *chD=endpoint->channelData;
      if( chD==NULL ) 
  	return JK_FALSE;
      sd=chD->sock;
  
      while(sent < len) {
          int this_time = send(sd, (char *)b + sent , len - sent,  0);
  	    
  	if(0 == this_time) {
  	    return -2;
  	}
  	if(this_time < 0) {
  	    return -3;
  	}
  	sent += this_time;
      }
      /*     return sent; */
      return JK_TRUE;
  }
  
  
  /** receive len bytes.
   * @param sd  opened socket.
   * @param b   buffer to store the data.
   * @param len length to receive.
   * @return    -1: receive failed or connection closed.
   *            >0: length of the received data.
   * Was: tcp_socket_recvfull
   */
  static int JK_METHOD jk_channel_socket_recv( jk_channel_t *_this,
                                               jk_endpoint_t *endpoint,
                                               char *b, int len ) 
  {
      jk_channel_socket_data_t *chD=endpoint->channelData;
      int sd;
      int rdlen;
  
      if( chD==NULL ) 
  	return JK_FALSE;
      sd=chD->sock;
      rdlen = 0;
      
      while(rdlen < len) {
  	int this_time = recv(sd, 
  			     (char *)b + rdlen, 
  			     len - rdlen, 
  			     0);	
  	if(-1 == this_time) {
  #ifdef WIN32
  	    if(SOCKET_ERROR == this_time) { 
  		errno = WSAGetLastError() - WSABASEERR;
  	    }
  #endif /* WIN32 */
  	    
  	    if(EAGAIN == errno) {
  		continue;
  	    } 
  	    return -1;
  	}
  	if(0 == this_time) {
  	    return -1; 
  	}
  	rdlen += this_time;
      }
      return rdlen; 
  }
  
  
  
  int JK_METHOD jk_channel_socket_factory(jk_env_t *env,
                                          void **result,
  					char *type,
                                          char *name)
  {
      jk_channel_t *channel;
      
      if( strcmp( "channel", type ) != 0 ) {
  	/* Wrong type  XXX throw */
  	*result=NULL;
  	return JK_FALSE;
      }
      channel=(jk_channel_t *)malloc( sizeof( jk_channel_t));
      channel->_privatePtr= (jk_channel_socket_private_t *)
  	malloc( sizeof( jk_channel_socket_private_t));
  
      channel->recv= &jk_channel_socket_recv; 
      channel->send= &jk_channel_socket_send; 
      channel->init= &jk_channel_socket_init; 
      channel->open= &jk_channel_socket_open; 
      channel->close= &jk_channel_socket_close; 
      channel->getProperty= &jk_channel_socket_getProperty; 
      channel->setProperty= &jk_channel_socket_setProperty; 
  
      channel->supportedProperties=( char ** )malloc( 4 * sizeof( char * ));
      channel->supportedProperties[0]="host";
      channel->supportedProperties[1]="port";
      channel->supportedProperties[2]="defaultPort";
      channel->supportedProperties[3]="\0";
  
      channel->name="file";
      
      *result= channel;
      
      return JK_TRUE;
  }
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/common/jk_connect.c
  
  Index: jk_connect.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 The Apache Software License,  Version 1.1                 *
   *                                                                           *
   *          Copyright (c) 1999-2001 The Apache Software Foundation.          *
   *                           All rights reserved.                            *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * Redistribution and use in source and binary forms,  with or without modi- *
   * fication, are permitted provided that the following conditions are met:   *
   *                                                                           *
   * 1. Redistributions of source code  must retain the above copyright notice *
   *    notice, this list of conditions and the following disclaimer.          *
   *                                                                           *
   * 2. Redistributions  in binary  form  must  reproduce the  above copyright *
   *    notice,  this list of conditions  and the following  disclaimer in the *
   *    documentation and/or other materials provided with the distribution.   *
   *                                                                           *
   * 3. The end-user documentation  included with the redistribution,  if any, *
   *    must include the following acknowlegement:                             *
   *                                                                           *
   *       "This product includes  software developed  by the Apache  Software *
   *        Foundation <http://www.apache.org/>."                              *
   *                                                                           *
   *    Alternately, this acknowlegement may appear in the software itself, if *
   *    and wherever such third-party acknowlegements normally appear.         *
   *                                                                           *
   * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software     *
   *    Foundation"  must not be used  to endorse or promote  products derived *
   *    from this  software without  prior  written  permission.  For  written *
   *    permission, please contact <apache@apache.org>.                        *
   *                                                                           *
   * 5. Products derived from this software may not be called "Apache" nor may *
   *    "Apache" appear in their names without prior written permission of the *
   *    Apache Software Foundation.                                            *
   *                                                                           *
   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
   * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY *
   * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL *
   * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY *
   * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL *
   * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS *
   * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) *
   * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT, *
   * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
   * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE *
   * POSSIBILITY OF SUCH DAMAGE.                                               *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * This software  consists of voluntary  contributions made  by many indivi- *
   * duals on behalf of the  Apache Software Foundation.  For more information *
   * on the Apache Software Foundation, please see <http://www.apache.org/>.   *
   *                                                                           *
   * ========================================================================= */
  
  /*
   * Description: Socket/Naming manipulation functions
   * Based on:    Various Jserv files
   */
  /**
   * @package	jk_connect
   * @author      Gal Shachor <shachor@il.ibm.com>
   * @version     $Revision: 1.1 $
   */
  
  
  #include "jk_connect.h"
  #include "jk_util.h"
  
  /** resolve the host IP */
   
  int jk_resolve(char *host,
                 short port,
                 struct sockaddr_in *rc) 
  {
      int x;
      u_long laddr;
  
      rc->sin_port   = htons((short)port);
      rc->sin_family = AF_INET;
  
      /* Check if we only have digits in the string */
      for(x = 0 ; '\0' != host[x] ; x++) {
          if(!isdigit(host[x]) && host[x] != '.') {
              break;
          }
      }
  
      if(host[x] != '\0') {
          /* If we found also characters we use gethostbyname()*/
          struct hostent *hoste = gethostbyname(host);
          if(!hoste) {
              return JK_FALSE;
          }
  
          laddr = ((struct in_addr *)hoste->h_addr_list[0])->s_addr;
      } else {
          /* If we found only digits we use inet_addr() */
          laddr = inet_addr(host);        
      }
      memcpy(&(rc->sin_addr), &laddr , sizeof(laddr));
  
      return JK_TRUE;
  }
  
  /** connect to Tomcat */
  
  int jk_open_socket(struct sockaddr_in *addr, 
                     int ndelay,
                     jk_logger_t *l)
  {
      int sock;
  
      jk_log(l, JK_LOG_DEBUG, "Into jk_open_socket\n");
  
      sock = socket(AF_INET, SOCK_STREAM, 0);
      if(sock > -1) {
          int ret;
          /* Tries to connect to JServ (continues trying while error is EINTR) */
          do {
              jk_log(l, JK_LOG_DEBUG, "jk_open_socket, try to connect socket = %d\n", sock);
              ret = connect(sock,
                            (struct sockaddr *)addr,
                            sizeof(struct sockaddr_in));
  #ifdef WIN32
              if(SOCKET_ERROR == ret) { 
                  errno = WSAGetLastError() - WSABASEERR;
              }
  #endif /* WIN32 */
              jk_log(l, JK_LOG_DEBUG, "jk_open_socket, after connect ret = %d\n", ret);
          } while (-1 == ret && EINTR == errno);
  
          /* Check if we connected */
          if(0 == ret) {
              if(ndelay) {
                  int set = 1;
  
                  jk_log(l, JK_LOG_DEBUG, "jk_open_socket, set TCP_NODELAY to on\n");
                  setsockopt(sock, 
                             IPPROTO_TCP, 
                             TCP_NODELAY, 
                             (char *)&set, 
                             sizeof(set));
              }   
  
              jk_log(l, JK_LOG_DEBUG, "jk_open_socket, return, sd = %d\n", sock);
              return sock;
          }   
          jk_log(l, JK_LOG_ERROR, "jk_open_socket, connect() failed errno = %d\n", errno);
          jk_close_socket(sock);
      } else {
  #ifdef WIN32
          errno = WSAGetLastError() - WSABASEERR;
  #endif /* WIN32 */
          jk_log(l, JK_LOG_ERROR, "jk_open_socket, socket() failed errno = %d\n", errno);
      }    
  
      return -1;
  }
  
  /** close the socket */
  
  int jk_close_socket(int s)
  {
  #ifdef WIN32
      if(INVALID_SOCKET  != s) {
          return closesocket(s) ? -1 : 0; 
      }
  #else 
      if(-1 != s) {
          return close(s); 
      }
  #endif
  
      return -1;
  }
  
  /** send a long message
   * @param sd  opened socket.
   * @param b   buffer containing the data.
   * @param len length to send.
   * @return    -2: send returned 0 ? what this that ?
   *            -3: send failed.
   *            >0: total size send.
   * @bug       this fails on Unixes if len is too big for the underlying
   *             protocol.
   */
  int jk_tcp_socket_sendfull(int sd, 
                             const unsigned char *b,
                             int len)
  {
      int sent = 0;
  
      while(sent < len) {
          int this_time = send(sd, 
                               (char *)b + sent , 
                               len - sent, 
                               0);
  	    
  	    if(0 == this_time) {
  	        return -2;
  	    }
  	    if(this_time < 0) {
  	        return -3;
  	    }
  	    sent += this_time;
      }
  
      return sent;
  }
  
  /** receive len bytes.
   * @param sd  opened socket.
   * @param b   buffer to store the data.
   * @param len length to receive.
   * @return    -1: receive failed or connection closed.
   *            >0: length of the received data.
   */
  int jk_tcp_socket_recvfull(int sd, 
                             unsigned char *b, 
                             int len) 
  {
      int rdlen = 0;
  
      while(rdlen < len) {
  	    int this_time = recv(sd, 
                               (char *)b + rdlen, 
                               len - rdlen, 
                               0);	
  	    if(-1 == this_time) {
  #ifdef WIN32
              if(SOCKET_ERROR == this_time) { 
                  errno = WSAGetLastError() - WSABASEERR;
              }
  #endif /* WIN32 */
  
      	    if(EAGAIN == errno) {
                  continue;
  	        } 
  		    return -1;
  	    }
          if(0 == this_time) {
              return -1; 
          }
  	    rdlen += this_time;
      }
  
      return rdlen;
  }
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/common/jk_context.c
  
  Index: jk_context.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 The Apache Software License,  Version 1.1                 *
   *                                                                           *
   *          Copyright (c) 1999-2001 The Apache Software Foundation.          *
   *                           All rights reserved.                            *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * Redistribution and use in source and binary forms,  with or without modi- *
   * fication, are permitted provided that the following conditions are met:   *
   *                                                                           *
   * 1. Redistributions of source code  must retain the above copyright notice *
   *    notice, this list of conditions and the following disclaimer.          *
   *                                                                           *
   * 2. Redistributions  in binary  form  must  reproduce the  above copyright *
   *    notice,  this list of conditions  and the following  disclaimer in the *
   *    documentation and/or other materials provided with the distribution.   *
   *                                                                           *
   * 3. The end-user documentation  included with the redistribution,  if any, *
   *    must include the following acknowlegement:                             *
   *                                                                           *
   *       "This product includes  software developed  by the Apache  Software *
   *        Foundation <http://www.apache.org/>."                              *
   *                                                                           *
   *    Alternately, this acknowlegement may appear in the software itself, if *
   *    and wherever such third-party acknowlegements normally appear.         *
   *                                                                           *
   * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software     *
   *    Foundation"  must not be used  to endorse or promote  products derived *
   *    from this  software without  prior  written  permission.  For  written *
   *    permission, please contact <apache@apache.org>.                        *
   *                                                                           *
   * 5. Products derived from this software may not be called "Apache" nor may *
   *    "Apache" appear in their names without prior written permission of the *
   *    Apache Software Foundation.                                            *
   *                                                                           *
   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
   * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY *
   * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL *
   * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY *
   * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL *
   * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS *
   * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) *
   * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT, *
   * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
   * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE *
   * POSSIBILITY OF SUCH DAMAGE.                                               *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * This software  consists of voluntary  contributions made  by many indivi- *
   * duals on behalf of the  Apache Software Foundation.  For more information *
   * on the Apache Software Foundation, please see <http://www.apache.org/>.   *
   *                                                                           *
   * ========================================================================= */
  
  /***************************************************************************
   * Description: Context handling (Autoconf)                                *
   * Author:      Henri Gomez <hgomez@slib.fr>                               *
   * Version:     $Revision: 1.1 $                                           *
   ***************************************************************************/
  
  #include "jk_global.h"
  #include "jk_context.h"
  #include "jk_ajp_common.h"
  
  
  /*
   * Set the virtual name of the context 
   */
  
  int context_set_virtual(jk_context_t *c, char *virtual)
  {
      if (c) {
  
          if (virtual) {
              c->virtual = jk_pool_strdup(&c->p, virtual);
  
              if (! c->virtual)
                  return JK_FALSE;
          }
  
          return JK_TRUE;
      }
  
      return JK_FALSE;
  }
  
  /*
   * Init the context info struct
   */
  
  int context_open(jk_context_t *c, char *virtual)
  {
      if (c) {
          jk_open_pool(&c->p, c->buf, sizeof(jk_pool_atom_t) * SMALL_POOL_SIZE);
          c->size  	= 0;
          c->capacity = 0;
          c->contexts = NULL;
  
          return context_set_virtual(c, virtual);
      }
  
      return JK_FALSE;
  }
  
  /*
   * Close the context info struct
   */
  
  int context_close(jk_context_t *c)
  {
      if (c) {
  
          jk_close_pool(&c->p);
          return JK_TRUE;
      }
  
      return JK_FALSE;
  }
  
  /*
   * Allocate and open context
   */
  
  int context_alloc(jk_context_t **c, char * virtual)
  {
      if (c) 
          return context_open(*c = (jk_context_t *)malloc(sizeof(jk_context_t)), virtual);
    
      return JK_FALSE;
  }
   
  /*
   * Close and destroy context
   */
  
  int context_free(jk_context_t **c)
  {
      if (c && *c) {
          context_close(*c);  
          free(*c);
          *c = NULL;
          return JK_TRUE;
      }
      
      return JK_FALSE;
  }
  
  
  /*
   * Ensure there will be memory in context info to store Context Bases
   */
  
  static int context_realloc(jk_context_t *c)
  {
      if (c->size == c->capacity) {
          jk_context_item_t **contexts;
          int  capacity = c->capacity + CBASE_INC_SIZE;
          
          contexts = (jk_context_item_t **)jk_pool_alloc(&c->p, sizeof(jk_context_item_t *) * capacity);
  
          if (! contexts)
              return JK_FALSE;
  
          if (c->capacity && c->contexts)
              memcpy(contexts, c->contexts, sizeof(jk_context_item_t *) * c->capacity);
  
          c->contexts = contexts;
          c->capacity = capacity;
      }
  
      return JK_TRUE;
  }
  
  /*
   * Ensure there will be memory in context info to URIS
   */
   
  static int context_item_realloc(jk_context_t *c, jk_context_item_t *ci)
  {
      if (ci->size == ci->capacity) {
              char **uris;
              int capacity = ci->capacity + URI_INC_SIZE;
  
              uris = (char **)jk_pool_alloc(&c->p, sizeof(char *) * capacity);
  
          if (! uris)
              return JK_FALSE;
  
          memcpy(uris, ci->uris, sizeof(char *) * ci->capacity);
  
          ci->uris     = uris;
          ci->capacity = capacity;
      }
      
      return JK_TRUE;
  }
  
          
  /*
   * Locate a context base in context list
   */
  
  jk_context_item_t * context_find_base(jk_context_t *c, char *cbase)
  {
      int                 i;
      jk_context_item_t * ci;
  
      if (! c || ! cbase)
          return NULL;
  
      for (i = 0 ; i < c->size ; i++) {
          
          ci = c->contexts[i];
  
          if (! ci)
              continue;
  
          if (! strcmp(ci->cbase, cbase))
              return ci;
      }
  
      return NULL;
  }
  
  /*
   * Locate an URI in a context item
   */
  
  char * context_item_find_uri(jk_context_item_t *ci, char *uri)
  {
      int i;
  
      if (! ci || ! uri)
          return NULL;
  
      for (i = 0 ; i < ci->size ; i++) {
          if (! strcmp(ci->uris[i], uri))
              return ci->uris[i];
      }
  
      return NULL;
  }
  
  void context_dump_uris(jk_context_t *c, char *cbase, FILE * f)
  {
      jk_context_item_t * ci;
      int                 i;
  
      ci = context_find_base(c, cbase);
  
      if (! ci)
          return;
  
      for (i = 0; i < ci->size; i++)
          fprintf(f, "/%s/%s\n", ci->cbase, ci->uris[i]);
  
      fflush(f); 
  }
  
  
  /*
   * Add a new context item to context
   */
  
  jk_context_item_t * context_add_base(jk_context_t *c, char *cbase)
  {
      jk_context_item_t *  ci;
  
      if (! c || !cbase)
          return NULL;
  
      /* Check if the context base was not allready created */
      ci = context_find_base(c, cbase);
  
      if (ci)
          return ci;
  
      if (context_realloc(c) != JK_TRUE)
          return NULL;
  
      ci = (jk_context_item_t *)jk_pool_alloc(&c->p, sizeof(jk_context_item_t));
  
      if (! ci)
          return NULL;
  
      c->contexts[c->size] = ci;
      c->size++;
      ci->cbase       = jk_pool_strdup(&c->p, cbase);
      ci->status      = 0;
      ci->size        = 0;
      ci->capacity    = 0;
      ci->uris        = NULL;
  
      return ci;
  }
  
  /*
   * Add a new URI to a context item
   */
  
  int context_add_uri(jk_context_t *c, char *cbase, char * uri)
  {
      jk_context_item_t *  ci;
  
      if (! uri)
          return JK_FALSE;
  
      /* Get/Create the context base */
      ci = context_add_base(c, cbase);
          
      if (! ci)
          return JK_FALSE;
  
      if (context_item_find_uri(ci, uri) != NULL)
          return JK_TRUE;
  
      if (context_item_realloc(c, ci) == JK_FALSE)
          return JK_FALSE;
  
      ci->uris[ci->size] = jk_pool_strdup(&c->p, uri);
  
      if (ci->uris[ci->size] == NULL)
          return JK_FALSE;
  
      ci->size++;
      return JK_TRUE;
  }
  
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/common/jk_env.c
  
  Index: jk_env.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 The Apache Software License,  Version 1.1                 *
   *                                                                           *
   *          Copyright (c) 1999-2001 The Apache Software Foundation.          *
   *                           All rights reserved.                            *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * Redistribution and use in source and binary forms,  with or without modi- *
   * fication, are permitted provided that the following conditions are met:   *
   *                                                                           *
   * 1. Redistributions of source code  must retain the above copyright notice *
   *    notice, this list of conditions and the following disclaimer.          *
   *                                                                           *
   * 2. Redistributions  in binary  form  must  reproduce the  above copyright *
   *    notice,  this list of conditions  and the following  disclaimer in the *
   *    documentation and/or other materials provided with the distribution.   *
   *                                                                           *
   * 3. The end-user documentation  included with the redistribution,  if any, *
   *    must include the following acknowlegement:                             *
   *                                                                           *
   *       "This product includes  software developed  by the Apache  Software *
   *        Foundation <http://www.apache.org/>."                              *
   *                                                                           *
   *    Alternately, this acknowlegement may appear in the software itself, if *
   *    and wherever such third-party acknowlegements normally appear.         *
   *                                                                           *
   * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software     *
   *    Foundation"  must not be used  to endorse or promote  products derived *
   *    from this  software without  prior  written  permission.  For  written *
   *    permission, please contact <apache@apache.org>.                        *
   *                                                                           *
   * 5. Products derived from this software may not be called "Apache" nor may *
   *    "Apache" appear in their names without prior written permission of the *
   *    Apache Software Foundation.                                            *
   *                                                                           *
   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
   * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY *
   * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL *
   * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY *
   * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL *
   * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS *
   * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) *
   * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT, *
   * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
   * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE *
   * POSSIBILITY OF SUCH DAMAGE.                                               *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * This software  consists of voluntary  contributions made  by many indivi- *
   * duals on behalf of the  Apache Software Foundation.  For more information *
   * on the Apache Software Foundation, please see <http://www.apache.org/>.   *
   *                                                                           *
   * ========================================================================= */
   
  #include "jk_env.h"
  
  /* Singleton for now */
  jk_env_t *jk_env_singleton;
  
  /* Private methods 
  */
  static jk_env_initEnv( jk_env_t *env, char *id );
  
  /* XXX We should have one env per thread to avoid sync problems. 
     The env will provide access to pools, etc 
  */
  
  jk_env_t* JK_METHOD jk_env_getEnv( char *id ) {
    if( jk_env_singleton == NULL ) {
      jk_env_singleton=(jk_env_t *)calloc( 1, sizeof( jk_env_t ));
      jk_env_initEnv( (jk_env_t *)jk_env_singleton, id );
    }
    return jk_env_singleton;
  }
  
  /* ==================== Implementation ==================== */
  
  
  static jk_env_objectFactory_t JK_METHOD jk_env_getFactory(jk_env_t *env, 
                                                            const char *type,
                                                            const char *name )
  {
    jk_env_objectFactory_t result;
    char *typeName=
        (char *)calloc( (strlen(name) + strlen(type) + 2 ), sizeof( char ));
  
    strcpy(typeName, type );
    strcat( typeName, "/" );
    strcat( typeName, name );
  
    if( type==NULL || name==NULL ) {
      // throw NullPointerException
      return NULL;
    }
  
    /** XXX add check for the type */
    result=(jk_env_objectFactory_t)map_get( env->_registry, typeName, NULL );
    return result;
  }
  
  static void *jk_env_getInstance( jk_env_t *_this, const char *type, const char *name )
  {
      jk_env_objectFactory_t fac;
      void *result;
  
      fac=_this->getFactory( _this, type, name);
      if( fac==NULL ) {
          jk_log(_this->logger, JK_LOG_ERROR,"Error getting factory for %s:%s\n", type, name);
          return NULL;
      }
  
      fac( _this, &result, type, name );
      if( result==NULL ) {
          jk_log(_this->logger, JK_LOG_ERROR,"Error getting instance for %s:%s\n", type, name);
          return NULL;
      }
      
      return result;
  }
  
  
  static void JK_METHOD jk_env_registerFactory(jk_env_t *env, 
                                               const char *type,
                                               const char *name, 
                                               jk_env_objectFactory_t fact)
  {
    void *old;
    char *typeName;
    int size=( sizeof( char ) * (strlen(name) + strlen(type) + 2 ));
  
    typeName=(char *)calloc(size, sizeof(char));
  
  
    strcpy(typeName, type );
    strcat( typeName, "/" );
    strcat( typeName, name );
    map_put( env->_registry, typeName, fact, &old );
  }
  
  static jk_env_initEnv( jk_env_t *env, char *id ) {
    /*   env->logger=NULL; */
    /*   map_alloc( & env->properties ); */
    env->getFactory= jk_env_getFactory; 
    env->registerFactory= jk_env_registerFactory;
    env->getInstance= jk_env_getInstance; 
    map_alloc( & env->_registry);
    jk_registry_init(env);
  }
  
  
  
  
  
  
  
  
  
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/common/jk_handler_discovery.c
  
  Index: jk_handler_discovery.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 The Apache Software License,  Version 1.1                 *
   *                                                                           *
   *          Copyright (c) 1999-2001 The Apache Software Foundation.          *
   *                           All rights reserved.                            *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * Redistribution and use in source and binary forms,  with or without modi- *
   * fication, are permitted provided that the following conditions are met:   *
   *                                                                           *
   * 1. Redistributions of source code  must retain the above copyright notice *
   *    notice, this list of conditions and the following disclaimer.          *
   *                                                                           *
   * 2. Redistributions  in binary  form  must  reproduce the  above copyright *
   *    notice,  this list of conditions  and the following  disclaimer in the *
   *    documentation and/or other materials provided with the distribution.   *
   *                                                                           *
   * 3. The end-user documentation  included with the redistribution,  if any, *
   *    must include the following acknowlegement:                             *
   *                                                                           *
   *       "This product includes  software developed  by the Apache  Software *
   *        Foundation <http://www.apache.org/>."                              *
   *                                                                           *
   *    Alternately, this acknowlegement may appear in the software itself, if *
   *    and wherever such third-party acknowlegements normally appear.         *
   *                                                                           *
   * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software     *
   *    Foundation"  must not be used  to endorse or promote  products derived *
   *    from this  software without  prior  written  permission.  For  written *
   *    permission, please contact <apache@apache.org>.                        *
   *                                                                           *
   * 5. Products derived from this software may not be called "Apache" nor may *
   *    "Apache" appear in their names without prior written permission of the *
   *    Apache Software Foundation.                                            *
   *                                                                           *
   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
   * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY *
   * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL *
   * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY *
   * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL *
   * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS *
   * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) *
   * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT, *
   * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
   * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE *
   * POSSIBILITY OF SUCH DAMAGE.                                               *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * This software  consists of voluntary  contributions made  by many indivi- *
   * duals on behalf of the  Apache Software Foundation.  For more information *
   * on the Apache Software Foundation, please see <http://www.apache.org/>.   *
   *                                                                           *
   * ========================================================================= */
  
  /**
   * Description: AJP14 Discovery handler
   * Author:      Henri Gomez <hgomez@slib.fr>
   * Version:     $Revision: 1.1 $                                          
   */
  
  #include "jk_global.h"
  #include "jk_context.h"
  #include "jk_pool.h"
  #include "jk_util.h"
  #include "jk_msg_buff.h"
  #include "jk_ajp_common.h"
  #include "jk_ajp14.h" 
  #include "jk_logger.h"
  #include "jk_service.h"
  
  
  
  
  /*
   * AJP14 Autoconf Phase
   *
   * CONTEXT QUERY / REPLY
   */
  
  #define MAX_URI_SIZE    512
  
  static int handle_discovery(ajp_endpoint_t  *ae,
                              jk_workerEnv_t *we,
                              jk_msg_buf_t    *msg,
                              jk_logger_t     *l)
  {
      int                 cmd;
      int                 i,j;
      jk_login_service_t  *jl = ae->worker->login;
      jk_context_item_t   *ci;
      jk_context_t        *c;  
      char                *buf;
  
  #ifndef TESTME
  
      ajp14_marshal_context_query_into_msgb(msg, we->virtual, l);
      
      jk_log(l, JK_LOG_DEBUG, "Into ajp14:discovery - send query\n");
  
      if (ajp_connection_tcp_send_message(ae, msg, l) != JK_TRUE)
          return JK_FALSE;
      
      jk_log(l, JK_LOG_DEBUG, "Into ajp14:discovery - wait context reply\n");
      
      jk_b_reset(msg);
      
      if (ajp_connection_tcp_get_message(ae, msg, l) != JK_TRUE)
          return JK_FALSE;
      
      if ((cmd = jk_b_get_byte(msg)) != AJP14_CONTEXT_INFO_CMD) {
          jk_log(l, JK_LOG_ERROR,
                 "Error ajp14:discovery - awaited command %d, received %d\n",
                 AJP14_CONTEXT_INFO_CMD, cmd);
          return JK_FALSE;
      }
      
      if (context_alloc(&c, we->virtual) != JK_TRUE) {
          jk_log(l, JK_LOG_ERROR,
                 "Error ajp14:discovery - can't allocate context room\n");
          return JK_FALSE;
      }
   
      if (ajp14_unmarshal_context_info(msg, c, l) != JK_TRUE) {
          jk_log(l, JK_LOG_ERROR,
                 "Error ajp14:discovery - can't get context reply\n");
          return JK_FALSE;
      }
  
      jk_log(l, JK_LOG_DEBUG, "Into ajp14:discovery - received context\n");
  
      buf = malloc(MAX_URI_SIZE);      /* Really a very long URI */
      
      if (! buf) {
          jk_log(l, JK_LOG_ERROR, "Error ajp14:discovery - can't alloc buf\n");
          return JK_FALSE;
      }
      
      for (i = 0; i < c->size; i++) {
          ci = c->contexts[i];
          for (j = 0; j < ci->size; j++) {
              
  #ifndef USE_SPRINTF
              snprintf(buf, MAX_URI_SIZE - 1, "/%s/%s", ci->cbase, ci->uris[j]);
  #else
              sprintf(buf, "/%s/%s", ci->cbase, ci->uris[j]);
  #endif
              
              jk_log(l, JK_LOG_INFO,
                     "Into ajp14:discovery "
                     "- worker %s will handle uri %s in context %s [%s]\n",
                     ae->worker->name, ci->uris[j], ci->cbase, buf);
              
  /* XXX UPDATE             uri_worker_map_add(we->uri_to_worker, buf, ae->worker->name, l); */
          }
      }
      
      free(buf);
      context_free(&c);
      
  #else 
      
      uri_worker_map_add(we->uri_to_worker,
                         "/examples/servlet/*",
                         ae->worker->name, l);
      uri_worker_map_add(we->uri_to_worker,
                         "/examples/*.jsp",
                         ae->worker->name, l);
      uri_worker_map_add(we->uri_to_worker,
                         "/examples/*.gif",
                         ae->worker->name, l);
  
  #endif 
      return JK_TRUE;
  }
   
  int discovery(ajp_endpoint_t *ae,
                jk_workerEnv_t *we,
                jk_logger_t    *l)
  {
      jk_pool_t     *p = &ae->pool;
      jk_msg_buf_t  *msg;
      int           rc;
  
      jk_log(l, JK_LOG_DEBUG, "Into ajp14:discovery\n");
      
      msg = jk_b_new(p);
      jk_b_set_buffer_size(msg, DEF_BUFFER_SZ);
      
      if ((rc = handle_discovery(ae, we, msg, l)) == JK_FALSE)
          ajp_close_endpoint(ae, l);
  
      return rc;
  }
  
  /* -------------------- private utils/marshaling -------------------- */
  
  /*
   * Build the Context Query Cmd (autoconf)
   *
   * +--------------------------+---------------------------------+
   * | CONTEXT QRY CMD (1 byte) | VIRTUAL HOST NAME (CString (*)) |
   * +--------------------------+---------------------------------+
   *
   */
  int ajp14_marshal_context_query_into_msgb(jk_msg_buf_t *msg,
                                            char         *virtual,
                                            jk_logger_t  *l)
  {
      jk_log(l, JK_LOG_DEBUG, "Into ajp14_marshal_context_query_into_msgb\n");
      
      /* To be on the safe side */
      jk_b_reset(msg);
      
      /*
       * CONTEXT QUERY CMD
       */
      if (jk_b_append_byte(msg, AJP14_CONTEXT_QRY_CMD))
          return JK_FALSE;
      
      /*
       * VIRTUAL HOST CSTRING
       */
      if (jk_b_append_string(msg, virtual)) {
          jk_log(l, JK_LOG_ERROR,
                 "Error ajp14_marshal_context_query_into_msgb "
                 "- Error appending the virtual host string\n");
          return JK_FALSE;
      }
      
      return JK_TRUE;
  }
  
  
  /*
   * Decode the Context Info Cmd (Autoconf)
   *
   * The Autoconf feature of AJP14, let us know which URL/URI could
   * be handled by the servlet-engine
   *
   * +---------------------------+---------------------------------+---------
   * | CONTEXT INFO CMD (1 byte) | VIRTUAL HOST NAME (CString (*)) | 
   * +---------------------------+---------------------------------+---------
   *
   *-------------------+-------------------------------+-----------+
   *CONTEXT NAME (CString (*)) | URL1 [\n] URL2 [\n] URL3 [\n] | NEXT CTX. |
   *-------------------+-------------------------------+-----------+
   */
  
  int ajp14_unmarshal_context_info(jk_msg_buf_t *msg,
                                   jk_context_t *c,
                                   jk_logger_t  *l)
  {
      char *vname;
      char *cname;
      char *uri;
      
      vname  = (char *)jk_b_get_string(msg);
  
      jk_log(l, JK_LOG_DEBUG,
             "ajp14_unmarshal_context_info - get virtual %s for virtual %s\n",
             vname, c->virtual);
  
      if (! vname) {
          jk_log(l, JK_LOG_ERROR,
                 "Error ajp14_unmarshal_context_info "
                 "- can't get virtual hostname\n");
          return JK_FALSE;
      }
      
      /* Check if we get the correct virtual host */
      if (c->virtual != NULL && 
  	vname != NULL &&
  	strcmp(c->virtual, vname)) {
          /* set the virtual name, better to add to a virtual list ? */
          
          if (context_set_virtual(c, vname) == JK_FALSE) {
              jk_log(l, JK_LOG_ERROR,
                     "Error ajp14_unmarshal_context_info "
                     "- can't malloc virtual hostname\n");
              return JK_FALSE;
          }
      }
      
      for (;;) {
          
          cname  = (char *)jk_b_get_string(msg); 
  
          if (! cname) {
              jk_log(l, JK_LOG_ERROR,
                     "Error ajp14_unmarshal_context_info - can't get context\n");
              return JK_FALSE;
          }   
          
          jk_log(l, JK_LOG_DEBUG, "ajp14_unmarshal_context_info "
                 "- get context %s for virtual %s\n", cname, vname);
          
          /* grab all contexts up to empty one which indicate end of contexts */
          if (! strlen(cname)) 
              break;
  
          /* create new context base (if needed) */
          
          if (context_add_base(c, cname) == JK_FALSE) {
              jk_log(l, JK_LOG_ERROR, "Error ajp14_unmarshal_context_info"
                     "- can't add/set context %s\n", cname);
              return JK_FALSE;
          }
          
          for (;;) {
              
              uri  = (char *)jk_b_get_string(msg);
              
              if (!uri) {
                  jk_log(l, JK_LOG_ERROR,
                         "Error ajp14_unmarshal_context_info - can't get URI\n");
                  return JK_FALSE;
              }
              
              if (! strlen(uri)) {
                  jk_log(l, JK_LOG_DEBUG, "No more URI for context %s", cname);
                  break;
              }
              
              jk_log(l, JK_LOG_INFO,
                     "Got URI (%s) for virtualhost %s and context %s\n",
                     uri, vname, cname);
              
              if (context_add_uri(c, cname, uri) == JK_FALSE) {
                  jk_log(l, JK_LOG_ERROR,
                         "Error ajp14_unmarshal_context_info - "
                         "can't add/set uri (%s) for context %s\n", uri, cname);
                  return JK_FALSE;
              } 
          }
      }
      return JK_TRUE;
  }
  
  
  /*
   * Build the Context State Query Cmd
   *
   * We send the list of contexts where we want to know state,
   * empty string end context list*
   * If cname is set, only ask about THIS context
   *
   * +----------------------------+----------------------------------+----------
   * | CONTEXT STATE CMD (1 byte) |  VIRTUAL HOST NAME  | CONTEXT NAME
   *                              |   (CString (*))     |  (CString (*)) 
   * +----------------------------+----------------------------------+----------
   *
   */
  int ajp14_marshal_context_state_into_msgb(jk_msg_buf_t *msg,
                                            jk_context_t *c,
                                            char         *cname,
                                            jk_logger_t  *l)
  {
      jk_context_item_t *ci;
      int                i;
      
      jk_log(l, JK_LOG_DEBUG, "Into ajp14_marshal_context_state_into_msgb\n");
      
      /* To be on the safe side */
      jk_b_reset(msg);
      
      /*
       * CONTEXT STATE CMD
       */
      if (jk_b_append_byte(msg, AJP14_CONTEXT_STATE_CMD))
          return JK_FALSE;
      
      /*
       * VIRTUAL HOST CSTRING
       */
       if (jk_b_append_string(msg, c->virtual)) {
          jk_log(l, JK_LOG_ERROR, "Error ajp14_marshal_context_state_into_msgb"
                 "- Error appending the virtual host string\n");
          return JK_FALSE;
       }
       
       if (cname) {
           
           ci = context_find_base(c, cname);
           
           if (! ci) {
               jk_log(l, JK_LOG_ERROR,
                      "Warning ajp14_marshal_context_state_into_msgb"
                      "- unknown context %s\n", cname);
              return JK_FALSE;
           }
           
           /*
            * CONTEXT CSTRING
            */
           
           if (jk_b_append_string(msg, cname )) {
              jk_log(l, JK_LOG_ERROR,
                     "Error ajp14_marshal_context_state_into_msgb"
                     "- Error appending the context string %s\n", cname);
              return JK_FALSE;
           }
       } else { /* Grab all contexts name */
           for (i = 0; i < c->size; i++) {
              /*
               * CONTEXT CSTRING
               */
               if (jk_b_append_string(msg, c->contexts[i]->cbase )) {
                   jk_log(l, JK_LOG_ERROR,
                          "Error ajp14_marshal_context_state_into_msgb "
                          "- Error appending the context string\n");
                   return JK_FALSE;
               }
           }
       }
       
       /* End of context list, an empty string */ 
       
       if (jk_b_append_string(msg, "")) {
           jk_log(l, JK_LOG_ERROR,
                  "Error ajp14_marshal_context_state_into_msgb "
                  "- Error appending end of contexts\n");
           return JK_FALSE;
       }
       
       return JK_TRUE;
  }
  
  
  /*
   * Decode the Context State Reply Cmd
   *
   * We get update of contexts list, empty string end context list*
   *
   * +----------------------------------+---------------------------------+----
   * | CONTEXT STATE REPLY CMD (1 byte) | VIRTUAL HOST NAME (CString (*)) | 
   * +----------------------------------+---------------------------------+----
   *
   *------------------------+------------------+----+
   *CONTEXT NAME (CString (*)) | UP/DOWN (1 byte) | .. |
   * ------------------------+------------------+----+
   */
  int ajp14_unmarshal_context_state_reply(jk_msg_buf_t *msg,
                                          jk_context_t *c,
                                          jk_logger_t  *l)
  {
      char                *vname;
      char                *cname;
      jk_context_item_t   *ci;
  
      /* get virtual name */
      vname  = (char *)jk_b_get_string(msg);
      
      if (! vname) {
          jk_log(l, JK_LOG_ERROR,
                 "Error ajp14_unmarshal_context_state_reply "
                 "- can't get virtual hostname\n");
          return JK_FALSE;
      }
      
      /* Check if we speak about the correct virtual */
      if (strcmp(c->virtual, vname)) {
          jk_log(l, JK_LOG_ERROR,
                 "Error ajp14_unmarshal_context_state_reply"
                 "- incorrect virtual %s instead of %s\n",
                 vname, c->virtual);
          return JK_FALSE;
      }
      
      for (;;) {
          /* get context name */
          cname  = (char *)jk_b_get_string(msg);
          
          if (! cname) {
              jk_log(l, JK_LOG_ERROR,
                     "Error ajp14_unmarshal_context_state_reply"
                     "- can't get context\n");
              return JK_FALSE;
          }	
          
          if (! strlen(cname))
              break;
          
          ci = context_find_base(c, cname);
          
          if (! ci) {
              jk_log(l, JK_LOG_ERROR,
                     "Error ajp14_unmarshal_context_state_reply "
                     "- unknow context %s for virtual %s\n", 
                     cname, vname);
              return JK_FALSE;
          }
          
          ci->status = jk_b_get_int(msg);
          
          jk_log(l, JK_LOG_DEBUG, "ajp14_unmarshal_context_state_reply "
                 "- updated context %s to state %d\n", cname, ci->status);
      }
      
      return JK_TRUE;
  }
  
  /*
   * Decode the Context Update Cmd
   * 
   * +-----------------------------+---------------------------------+------
   * | CONTEXT UPDATE CMD (1 byte) | VIRTUAL HOST NAME (CString (*)) | 
   * +-----------------------------+---------------------------------+------
   *
   * ----------------------+------------------+
   * CONTEXT NAME (CString (*)) | UP/DOWN (1 byte) |
   * ----------------------+------------------+
   * 
   */
  int ajp14_unmarshal_context_update_cmd(jk_msg_buf_t *msg,
                                         jk_context_t *c,
                                         jk_logger_t  *l)
  {
      return (ajp14_unmarshal_context_state_reply(msg, c, l));
  }
  
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/common/jk_handler_logon.c
  
  Index: jk_handler_logon.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 The Apache Software License,  Version 1.1                 *
   *                                                                           *
   *          Copyright (c) 1999-2001 The Apache Software Foundation.          *
   *                           All rights reserved.                            *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * Redistribution and use in source and binary forms,  with or without modi- *
   * fication, are permitted provided that the following conditions are met:   *
   *                                                                           *
   * 1. Redistributions of source code  must retain the above copyright notice *
   *    notice, this list of conditions and the following disclaimer.          *
   *                                                                           *
   * 2. Redistributions  in binary  form  must  reproduce the  above copyright *
   *    notice,  this list of conditions  and the following  disclaimer in the *
   *    documentation and/or other materials provided with the distribution.   *
   *                                                                           *
   * 3. The end-user documentation  included with the redistribution,  if any, *
   *    must include the following acknowlegement:                             *
   *                                                                           *
   *       "This product includes  software developed  by the Apache  Software *
   *        Foundation <http://www.apache.org/>."                              *
   *                                                                           *
   *    Alternately, this acknowlegement may appear in the software itself, if *
   *    and wherever such third-party acknowlegements normally appear.         *
   *                                                                           *
   * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software     *
   *    Foundation"  must not be used  to endorse or promote  products derived *
   *    from this  software without  prior  written  permission.  For  written *
   *    permission, please contact <apache@apache.org>.                        *
   *                                                                           *
   * 5. Products derived from this software may not be called "Apache" nor may *
   *    "Apache" appear in their names without prior written permission of the *
   *    Apache Software Foundation.                                            *
   *                                                                           *
   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
   * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY *
   * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL *
   * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY *
   * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL *
   * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS *
   * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) *
   * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT, *
   * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
   * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE *
   * POSSIBILITY OF SUCH DAMAGE.                                               *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * This software  consists of voluntary  contributions made  by many indivi- *
   * duals on behalf of the  Apache Software Foundation.  For more information *
   * on the Apache Software Foundation, please see <http://www.apache.org/>.   *
   *                                                                           *
   * ========================================================================= */
  
  /**
   * Description: AJP14 Login handler
   * Author:      Henri Gomez <hgomez@slib.fr>
   * Version:     $Revision: 1.1 $                                          
   */
  
  #include "jk_global.h"
  #include "jk_context.h"
  #include "jk_pool.h"
  #include "jk_util.h"
  #include "jk_msg_buff.h"
  #include "jk_ajp_common.h"
  #include "jk_ajp14.h" 
  #include "jk_md5.h"
  #include "jk_logger.h"
  #include "jk_service.h"
  
  /* Private definitions */
  
  /*
   * Initial Login Phase (web server -> servlet engine)
   */
  #define AJP14_LOGINIT_CMD	(unsigned char)0x10
  
  /*
   * Second Login Phase (servlet engine -> web server), md5 seed is received
   */
  #define AJP14_LOGSEED_CMD	(unsigned char)0x11
  
  /*
   * Third Login Phase (web server -> servlet engine), md5 of seed + secret is sent
   */
  #define AJP14_LOGCOMP_CMD	(unsigned char)0x12
  
  /*
   * Login Accepted (servlet engine -> web server)
   */
  #define AJP14_LOGOK_CMD		(unsigned char)0x13
  
  /*
   * Login Rejected (servlet engine -> web server), will be logged
   */
  #define AJP14_LOGNOK_CMD	(unsigned char)0x14
  
  
  /* Private functions */
  
  static void ajp14_compute_md5(jk_login_service_t *s, 
                                jk_logger_t *l);
  
  static int ajp14_marshal_login_init_into_msgb(jk_msg_buf_t *msg, 
                                                jk_login_service_t *s, 
                                                jk_logger_t *l);
  
  static int ajp14_unmarshal_login_seed(jk_msg_buf_t *msg, 
                                        jk_login_service_t *s, 
                                        jk_logger_t *l);
  
  static  int ajp14_marshal_login_comp_into_msgb(jk_msg_buf_t *msg, 
                                                 jk_login_service_t *s, 
                                                 jk_logger_t *l);
  
  static int ajp14_unmarshal_log_ok(jk_msg_buf_t *msg, 
                                    jk_login_service_t *s, 
                                    jk_logger_t *l);
  
  static int ajp14_unmarshal_log_nok(jk_msg_buf_t *msg, 
                                     jk_logger_t *l);
  
  
  /* 
   * AJP14 Logon Phase 
   *
   * INIT + REPLY / NEGO + REPLY 
   */
  static int handle_logon(ajp_endpoint_t *ae,
                          jk_msg_buf_t	   *msg,
                          jk_logger_t     *l)
  {
      int	cmd;
      
      jk_login_service_t *jl = ae->worker->login;
      
      ajp14_marshal_login_init_into_msgb(msg, jl, l);
      
      jk_log(l, JK_LOG_DEBUG, "Into ajp14:logon - send init\n");
      
      if (ajp_connection_tcp_send_message(ae, msg, l) != JK_TRUE)	
          return JK_FALSE;
      
      jk_log(l, JK_LOG_DEBUG, "Into ajp14:logon - wait init reply\n");
      
      jk_b_reset(msg);
      
      if (ajp_connection_tcp_get_message(ae, msg, l) != JK_TRUE)
          return JK_FALSE;
      
      if ((cmd = jk_b_get_byte(msg)) != AJP14_LOGSEED_CMD) {
          jk_log(l, JK_LOG_ERROR,
                 "Error ajp14:logon: awaited command %d, received %d\n",
                 AJP14_LOGSEED_CMD, cmd);
          return JK_FALSE;
      }
      
      if (ajp14_unmarshal_login_seed(msg, jl, l) != JK_TRUE)
          return JK_FALSE;
      
      jk_log(l, JK_LOG_DEBUG,
             "Into ajp14:logon - received entropy %s\n", jl->entropy);
      
      ajp14_compute_md5(jl, l);
      
      if (ajp14_marshal_login_comp_into_msgb(msg, jl, l) != JK_TRUE)
          return JK_FALSE;
      
      if (ajp_connection_tcp_send_message(ae, msg, l) != JK_TRUE) 
          return JK_FALSE;
      
      jk_b_reset(msg);
      
      if (ajp_connection_tcp_get_message(ae, msg, l) != JK_TRUE)
          return JK_FALSE;
      
      switch (jk_b_get_byte(msg)) {
          
      case AJP14_LOGOK_CMD  :	
          if (ajp14_unmarshal_log_ok(msg, jl, l) == JK_TRUE) {
              jk_log(l, JK_LOG_DEBUG,
                     "Successfully connected to servlet-engine %s\n",
                     jl->servlet_engine_name);
              return JK_TRUE;
          }
          break;
          
      case AJP14_LOGNOK_CMD :
          ajp14_unmarshal_log_nok(msg, l);
          break;
      }
      
      return JK_FALSE;
  }
  
  int logon(ajp_endpoint_t *ae,
            jk_logger_t    *l)
  {
      jk_pool_t     *p = &ae->pool;
      jk_msg_buf_t  *msg;
      int 	  rc;
      
      jk_log(l, JK_LOG_DEBUG, "Into ajp14:logon\n");
  
      msg = jk_b_new(p);
      jk_b_set_buffer_size(msg, DEF_BUFFER_SZ);
      
      if ((rc = handle_logon(ae, msg, l)) == JK_FALSE) 
          ajp_close_endpoint(ae, l);
      
      return rc;
  }
  
  /* -------------------- private utils/marshaling -------------------- */
  
  /*
   * Compute the MD5 with ENTROPY / SECRET KEY
   */
  static void ajp14_compute_md5(jk_login_service_t *s, 
                                jk_logger_t        *l)
  {
      jk_md5((const unsigned char *)s->entropy,
             (const unsigned char *)s->secret_key, s->computed_key);
  
      jk_log(l, JK_LOG_DEBUG,
             "Into ajp14_compute_md5 (%s/%s) -> (%s)\n",
             s->entropy, s->secret_key, s->computed_key);
  }
  
  /*
   * Build the Login Init Command
   *
   * +-------------------------+---------------------------+-------------------
   * | LOGIN INIT CMD (1 byte) | NEGOCIATION DATA (32bits) | WEB SERVER INFO
   * |                         |                           |    (CString) 
   * +-------------------------+---------------------------+-------------------
   *
   */
  static int ajp14_marshal_login_init_into_msgb(jk_msg_buf_t       *msg,
                                                jk_login_service_t *s,
                                                jk_logger_t        *l)
  {
      jk_log(l, JK_LOG_DEBUG, "Into ajp14_marshal_login_init_into_msgb\n");
      
      /* To be on the safe side */
      jk_b_reset(msg);
      
      /*
       * LOGIN
       */
      if (jk_b_append_byte(msg, AJP14_LOGINIT_CMD)) 
          return JK_FALSE;
      
      /*
       * NEGOCIATION FLAGS
       */
      if (jk_b_append_long(msg, s->negociation))
          return JK_FALSE;
      
      /*
       * WEB-SERVER NAME
       */
      if (jk_b_append_string(msg, s->web_server_name)) {
          jk_log(l, JK_LOG_ERROR,
                 "Error ajp14_marshal_login_init_into_msgb "
                 "- Error appending the web_server_name string\n");
          return JK_FALSE;
      }
      
      return JK_TRUE;
  }
  
  
  /*
   * Decode the Login Seed Command
   *
   * +-------------------------+---------------------------+
   * | LOGIN SEED CMD (1 byte) | MD5 of entropy (32 chars) |
   * +-------------------------+---------------------------+
   *
   */
  static int ajp14_unmarshal_login_seed(jk_msg_buf_t       *msg,
                                        jk_login_service_t *s,
                                        jk_logger_t        *l)
  {
      if (jk_b_get_bytes(msg, (unsigned char *)s->entropy,
                         AJP14_ENTROPY_SEED_LEN) < 0) {
          jk_log(l, JK_LOG_ERROR,
                 "Error ajp14_unmarshal_login_seed - can't get seed\n");
          return JK_FALSE;
      }
  
      s->entropy[AJP14_ENTROPY_SEED_LEN] = 0;	/* Just to have a CString */
      return JK_TRUE;
  }
  
  /*
   * Build the Login Computed Command
   *
   * +-------------------------+---------------------------------------+
   * | LOGIN COMP CMD (1 byte) | MD5 of RANDOM + SECRET KEY (32 chars) |
   * +-------------------------+---------------------------------------+
   *
   */
  static int ajp14_marshal_login_comp_into_msgb(jk_msg_buf_t       *msg,
                                                jk_login_service_t *s,
                                                jk_logger_t        *l)
  {
      jk_log(l, JK_LOG_DEBUG, "Into ajp14_marshal_login_comp_into_msgb\n");
      
      /* To be on the safe side */
      jk_b_reset(msg);
  
      /*
       * LOGIN
       */
      if (jk_b_append_byte(msg, AJP14_LOGCOMP_CMD)) 
          return JK_FALSE;
  
      /*
       * COMPUTED-SEED
       */
       if (jk_b_append_bytes(msg, (const unsigned char *)s->computed_key,
                             AJP14_COMPUTED_KEY_LEN)) {
           jk_log(l, JK_LOG_ERROR,
                  "Error ajp14_marshal_login_comp_into_msgb "
                  " - Error appending the COMPUTED MD5 bytes\n");
          return JK_FALSE;
      }
  
      return JK_TRUE;
  }
  
  
  /*
   * Decode the LogOk Command
   *
   * +--------------------+------------------------+---------------------------
   * | LOGOK CMD (1 byte) | NEGOCIED DATA (32bits) | SERVLET ENGINE INFO(CString)
   * +--------------------+------------------------+---------------------------
   *
   */
  static int ajp14_unmarshal_log_ok(jk_msg_buf_t       *msg,
                                    jk_login_service_t *s,
                                    jk_logger_t        *l)
  {
      unsigned long 	nego;
      char *			sname;
      
      nego = jk_b_get_long(msg);
      
      if (nego == 0xFFFFFFFF) {
          jk_log(l, JK_LOG_ERROR,
                 "Error ajp14_unmarshal_log_ok - can't get negociated data\n");
          return JK_FALSE;
      }
      
      sname = (char *)jk_b_get_string(msg);
      
      if (! sname) {
          jk_log(l, JK_LOG_ERROR,
                 "Error ajp14_unmarshal_log_ok - "
                 "can't get servlet engine name\n");
          return JK_FALSE;
      }
  
      /* take care of removing previously allocated data */
      if (s->servlet_engine_name)			
          free(s->servlet_engine_name);
      
      s->servlet_engine_name = strdup(sname);
      
      if (! s->servlet_engine_name) {
          jk_log(l, JK_LOG_ERROR,
                 "Error ajp14_unmarshal_log_ok - "
                 " can't malloc servlet engine name\n");
          return JK_FALSE;
      }
      
      return JK_TRUE;
  }
  
  
  /*
   * Decode the Log Nok Command 
   *
   * +---------------------+-----------------------+
   * | LOGNOK CMD (1 byte) | FAILURE CODE (32bits) |
   * +---------------------+-----------------------+
   *
   */
  
  static int ajp14_unmarshal_log_nok(jk_msg_buf_t *msg,
                                     jk_logger_t  *l)
  {
      unsigned long   status;
      
      jk_log(l, JK_LOG_DEBUG, "Into ajp14_unmarshal_log_nok\n");
      
      status = jk_b_get_long(msg);
      
      if (status == 0xFFFFFFFF) {
          jk_log(l, JK_LOG_ERROR,
                 "Error ajp14_unmarshal_log_nok - can't get failure code\n");
          return JK_FALSE;
      }
      
      jk_log(l, JK_LOG_INFO,
             "Can't Log with servlet engine - code %08lx", status);
      return JK_TRUE;
  }
  
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/common/jk_logger.c
  
  Index: jk_logger.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 The Apache Software License,  Version 1.1                 *
   *                                                                           *
   *          Copyright (c) 1999-2001 The Apache Software Foundation.          *
   *                           All rights reserved.                            *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * Redistribution and use in source and binary forms,  with or without modi- *
   * fication, are permitted provided that the following conditions are met:   *
   *                                                                           *
   * 1. Redistributions of source code  must retain the above copyright notice *
   *    notice, this list of conditions and the following disclaimer.          *
   *                                                                           *
   * 2. Redistributions  in binary  form  must  reproduce the  above copyright *
   *    notice,  this list of conditions  and the following  disclaimer in the *
   *    documentation and/or other materials provided with the distribution.   *
   *                                                                           *
   * 3. The end-user documentation  included with the redistribution,  if any, *
   *    must include the following acknowlegement:                             *
   *                                                                           *
   *       "This product includes  software developed  by the Apache  Software *
   *        Foundation <http://www.apache.org/>."                              *
   *                                                                           *
   *    Alternately, this acknowlegement may appear in the software itself, if *
   *    and wherever such third-party acknowlegements normally appear.         *
   *                                                                           *
   * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software     *
   *    Foundation"  must not be used  to endorse or promote  products derived *
   *    from this  software without  prior  written  permission.  For  written *
   *    permission, please contact <apache@apache.org>.                        *
   *                                                                           *
   * 5. Products derived from this software may not be called "Apache" nor may *
   *    "Apache" appear in their names without prior written permission of the *
   *    Apache Software Foundation.                                            *
   *                                                                           *
   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
   * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY *
   * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL *
   * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY *
   * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL *
   * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS *
   * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) *
   * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT, *
   * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
   * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE *
   * POSSIBILITY OF SUCH DAMAGE.                                               *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * This software  consists of voluntary  contributions made  by many indivi- *
   * duals on behalf of the  Apache Software Foundation.  For more information *
   * on the Apache Software Foundation, please see <http://www.apache.org/>.   *
   *                                                                           *
   * ========================================================================= */
  
  /***************************************************************************
   * Description: Utility functions (mainly configuration)                   *
   * Author:      Gal Shachor <shachor@il.ibm.com>                           *
   * Author:      Henri Gomez <hgomez@slib.fr>                               *
   * Version:     $Revision: 1.1 $                                           *
   ***************************************************************************/
  
  #include "jk_util.h"
  
  #define LOG_FORMAT		    ("log_format")
  
  #define HUGE_BUFFER_SIZE (8*1024)
  #define LOG_LINE_SIZE    (1024)
  
  struct file_logger {
      FILE *logfile;
  };
  typedef struct file_logger file_logger_t;
  
  /* 
   * define the log format, we're using by default the one from error.log 
   *
   * [Mon Mar 26 19:44:48 2001] [jk_uri_worker_map.c (155)]: Into jk_uri_worker_map_t::uri_worker_map_alloc
   * log format used by apache in error.log
   */
  #ifndef JK_TIME_FORMAT 
  #define JK_TIME_FORMAT "[%a %b %d %H:%M:%S %Y] "
  #endif
  
  const char * jk_log_fmt = JK_TIME_FORMAT;
  
  static void set_time_str(char * str, int len)
  {
  	time_t		t = time(NULL);
      	struct tm 	*tms;
  
          if( t==NULL ) return;
          
      	tms = gmtime(&t);
          if( tms==NULL ) return;
  	strftime(str, len, jk_log_fmt, tms);
  }
  
  static int JK_METHOD log_to_file(jk_logger_t *l,                                 
                                   int level,
                                   const char *what)
  {
      if(l && l->level <= level && l->logger_private && what) {       
          unsigned sz = strlen(what);
          if(sz) {
              file_logger_t *p = l->logger_private;
              fwrite(what, 1, sz, p->logfile);
  	    /* [V] Flush the dam' thing! */
  	    fflush(p->logfile);
          }
  
          return JK_TRUE;
      }
  
      return JK_FALSE;
  }
  
  int jk_parse_log_level(const char *level)
  {
      if(0 == strcasecmp(level, JK_LOG_INFO_VERB)) {
          return JK_LOG_INFO_LEVEL;
      }
  
      if(0 == strcasecmp(level, JK_LOG_ERROR_VERB)) {
          return JK_LOG_ERROR_LEVEL;
      }
  
      if(0 == strcasecmp(level, JK_LOG_EMERG_VERB)) {
          return JK_LOG_EMERG_LEVEL;
      }
  
      return JK_LOG_DEBUG_LEVEL;
  }
  
  int jk_open_file_logger(jk_logger_t **l,
                          const char *file,
                          int level)
  {
      if(l && file) {     
          jk_logger_t *rc = (jk_logger_t *)malloc(sizeof(jk_logger_t));
          file_logger_t *p = (file_logger_t *)malloc(sizeof(file_logger_t));
          if(rc && p) {
              rc->log = log_to_file;
              rc->level = level;
              rc->logger_private = p;
              p->logfile = fopen(file, "a+");
              if(p->logfile) {
                  *l = rc;
                  return JK_TRUE;
              }           
          }
          if(rc) {
              free(rc);
          }
          if(p) {
              free(p);
          }
  
          *l = NULL;
      }
      return JK_FALSE;
  }
  
  int jk_close_file_logger(jk_logger_t **l)
  {
      if(l && *l) {
          file_logger_t *p = (*l)->logger_private;
          fflush(p->logfile);
          fclose(p->logfile);
          free(p);
          free(*l);
          *l = NULL;
  
          return JK_TRUE;
      }
      return JK_FALSE;
  }
  
  int jk_log(jk_logger_t *l,
             const char *file,
             int line,
             int level,
             const char *fmt, ...)
  {
      int rc = 0;
      
      if( !file || !fmt) {
          return -1;
      }
  
      if(l==NULL ||
         l->level <= level) {
  #ifdef NETWARE
  /* On NetWare, this can get called on a thread that has a limited stack so */
  /* we will allocate and free the temporary buffer in this function         */
          char *buf;
  #else
          char buf[HUGE_BUFFER_SIZE];
  #endif
          char *f = (char *)(file + strlen(file) - 1);
          va_list args;
          int used = 0;
  
          while(f != file && '\\' != *f && '/' != *f) {
              f--;
          }
          if(f != file) {
              f++;
          }
  
  #ifdef WIN32
  	set_time_str(buf, HUGE_BUFFER_SIZE);
  	used = strlen(buf);
          used += _snprintf(&buf[used], HUGE_BUFFER_SIZE, " [%s (%d)]: ", f, line);        
  #elif defined(NETWARE) /* until we get a snprintf function */
          buf = (char *) malloc(HUGE_BUFFER_SIZE);
          if (NULL == buf)
             return -1;
  
  	set_time_str(buf, HUGE_BUFFER_SIZE);
  	used = strlen(buf);
          used += sprintf(&buf[used], " [%s (%d)]: ", f, line);
  #else 
  	set_time_str(buf, HUGE_BUFFER_SIZE);
  	used = strlen(buf);
          used += snprintf(&buf[used], HUGE_BUFFER_SIZE, " [%s (%d)]: ", f, line);        
  #endif
          if(used < 0) {
              return 0; /* [V] not sure what to return... */
          }
      
          va_start(args, fmt);
  #ifdef WIN32
          rc = _vsnprintf(buf + used, HUGE_BUFFER_SIZE - used, fmt, args);
  #elif defined(NETWARE) /* until we get a vsnprintf function */
          rc = vsprintf(buf + used, fmt, args);
  #else 
          rc = vsnprintf(buf + used, HUGE_BUFFER_SIZE - used, fmt, args);
  #endif
          va_end(args);
          if( l!=NULL ) {        
              l->log(l, level, buf);
          } else {
              /* This is usefull to debug what happens before logger is set.
                 On apache you need -X option ( no detach, single process ) */
              printf("%s", buf );
          }
  #ifdef NETWARE
          free(buf);
  #endif
      }
      
      return rc;
  }
  
  
  void jk_set_log_format(const char * logformat)
  {
  	jk_log_fmt = (logformat) ? logformat : JK_TIME_FORMAT;
  }
  
  int jk_file_exists(const char *f)
  {
      if(f) {
          struct stat st;
          if((0 == stat(f, &st)) && (st.st_mode & S_IFREG)) {
              return JK_TRUE;
          }
      }
      return JK_FALSE;
  }
  
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/common/jk_map.c
  
  Index: jk_map.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 The Apache Software License,  Version 1.1                 *
   *                                                                           *
   *          Copyright (c) 1999-2001 The Apache Software Foundation.          *
   *                           All rights reserved.                            *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * Redistribution and use in source and binary forms,  with or without modi- *
   * fication, are permitted provided that the following conditions are met:   *
   *                                                                           *
   * 1. Redistributions of source code  must retain the above copyright notice *
   *    notice, this list of conditions and the following disclaimer.          *
   *                                                                           *
   * 2. Redistributions  in binary  form  must  reproduce the  above copyright *
   *    notice,  this list of conditions  and the following  disclaimer in the *
   *    documentation and/or other materials provided with the distribution.   *
   *                                                                           *
   * 3. The end-user documentation  included with the redistribution,  if any, *
   *    must include the following acknowlegement:                             *
   *                                                                           *
   *       "This product includes  software developed  by the Apache  Software *
   *        Foundation <http://www.apache.org/>."                              *
   *                                                                           *
   *    Alternately, this acknowlegement may appear in the software itself, if *
   *    and wherever such third-party acknowlegements normally appear.         *
   *                                                                           *
   * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software     *
   *    Foundation"  must not be used  to endorse or promote  products derived *
   *    from this  software without  prior  written  permission.  For  written *
   *    permission, please contact <apache@apache.org>.                        *
   *                                                                           *
   * 5. Products derived from this software may not be called "Apache" nor may *
   *    "Apache" appear in their names without prior written permission of the *
   *    Apache Software Foundation.                                            *
   *                                                                           *
   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
   * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY *
   * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL *
   * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY *
   * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL *
   * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS *
   * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) *
   * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT, *
   * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
   * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE *
   * POSSIBILITY OF SUCH DAMAGE.                                               *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * This software  consists of voluntary  contributions made  by many indivi- *
   * duals on behalf of the  Apache Software Foundation.  For more information *
   * on the Apache Software Foundation, please see <http://www.apache.org/>.   *
   *                                                                           *
   * ========================================================================= */
  
  /***************************************************************************
   * Description: General purpose map object                                 *
   * Author:      Gal Shachor <shachor@il.ibm.com>                           *
   * Version:     $Revision: 1.1 $                                           *
   ***************************************************************************/
  
  #include "jk_global.h"
  #include "jk_map.h"
  #include "jk_pool.h"
  #include "jk_map.h"
  #include "jk_util.h"
  
  #define CAPACITY_INC_SIZE (50)
  #define LENGTH_OF_LINE    (1024)
  
  struct jk_map {
      jk_pool_t p;
      jk_pool_atom_t buf[SMALL_POOL_SIZE];
  
      const char **names;
      const void **values;
  
      unsigned capacity;
      unsigned size;
  };
  
  static void trim_prp_comment(char *prp);
  static int trim(char *s);
  static int map_realloc(jk_map_t *m);
  
  int map_alloc(jk_map_t **m)
  {
      if(m) {
          return map_open(*m = (jk_map_t *)malloc(sizeof(jk_map_t)));
      }
      
      return JK_FALSE;
  }
  
  int map_free(jk_map_t **m)
  {
      int rc = JK_FALSE;
  
      if(m && *m) {
          map_close(*m);  
          free(*m);
          *m = NULL;
      }
      
      return rc;
  }
  
  int map_open(jk_map_t *m)
  {
      int rc = JK_FALSE;
  
      if(m) {
          jk_open_pool(&m->p, m->buf, sizeof(jk_pool_atom_t) * SMALL_POOL_SIZE);
          m->capacity = 0;
          m->size     = 0;
          m->names    = NULL;
          m->values   = NULL;
          rc = JK_TRUE;
      }
      
      return rc;
  }
  
  int map_close(jk_map_t *m)
  {
      int rc = JK_FALSE;
  
      if(m) {
          jk_close_pool(&m->p);
          rc = JK_TRUE;
      }
      
      return rc;
  }
  
  void *map_get(jk_map_t *m,
                const char *name,
                const void *def)
  {
      const void *rc = (void *)def;
      
      if(m && name) {
          unsigned i;
          for(i = 0 ; i < m->size ; i++) {
              if(0 == strcmp(m->names[i], name)) {
                  rc = m->values[i];
                  break;
              }
          }
      }
  
      return (void *)rc; /* DIRTY */
  }
  
  int map_get_int(jk_map_t *m,
                  const char *name,
                  int def)
  {
      char buf[100];
      char *rc;
      int  len;
      int  int_res;
      int  multit = 1;
  
      sprintf(buf, "%d", def);
      rc = map_get_string(m, name, buf);
  
      len = strlen(rc);
      if(len) {        
          char *lastchar = rc + len - 1;
          if('m' == *lastchar || 'M' == *lastchar) {
              *lastchar = '\0';
              multit = 1024 * 1024;
          } else if('k' == *lastchar || 'K' == *lastchar) {
              *lastchar = '\0';
              multit = 1024;
          }
      }
  
      int_res = atoi(rc);
  
      return int_res * multit;
  }
  
  double map_get_double(jk_map_t *m,
                        const char *name,
                        double def)
  {
      char buf[100];
      char *rc;
  
      sprintf(buf, "%f", def);
      rc = map_get_string(m, name, buf);
  
      return atof(rc);
  }
  
  char *map_get_string(jk_map_t *m,
                      const char *name,
                      const char *def)
  {
      return map_get(m, name, def);
  }
  
  char **map_get_string_list(jk_map_t *m,
                             const char *name,
                             unsigned *list_len,
                             const char *def)
  {
      char *l = map_get_string(m, name, def);
      char **ar = NULL;
  
      *list_len = 0;
  
      if(l) {
          unsigned capacity = 0;
          unsigned idex = 0;    
          char *v = jk_pool_strdup(&m->p, l);
          
          if(!v) {
              return NULL;
          }
  
          /*
           * GS, in addition to VG's patch, we now need to 
           * strtok also by a "*"
           */
  
          for(l = strtok(v, " \t,*") ; 
              l ; 
              l = strtok(NULL, " \t,*")) {
          
              if(idex == capacity) {
                  ar = jk_pool_realloc(&m->p, 
                                       sizeof(char *) * (capacity + 5),
                                       ar,
                                       sizeof(char *) * capacity);
                  if(!ar) {
                      return JK_FALSE;
                  }
                  capacity += 5;
              }
              ar[idex] = jk_pool_strdup(&m->p, l);
              idex ++;
          }
          
          *list_len = idex;
      }
  
      return ar;
  }
  
  int map_put(jk_map_t *m,
              const char *name,
              const void *value,
              void **old)
  {
      int rc = JK_FALSE;
  
      if(m && name ) {
          unsigned i;
          for(i = 0 ; i < m->size ; i++) {
              if(0 == strcmp(m->names[i], name)) {
                  break;
              }
          }
  
          if(i < m->size) {
              if( old!=NULL )
                  *old = (void *) m->values[i]; /* DIRTY */
              m->values[i] = value;
              rc = JK_TRUE;
          } else {
              map_realloc(m);
  
              if(m->size < m->capacity) {
                  m->values[m->size] = value;
                  m->names[m->size] = jk_pool_strdup(&m->p, name);
                  m->size ++;
                  rc = JK_TRUE;
              }
          }       
      }
  
      return rc;
  }
  
  int map_read_properties(jk_map_t *m,
                          const char *f)
  {
      int rc = JK_FALSE;
  
      if(m && f) {
          FILE *fp = fopen(f, "r");
          
          if(fp) {
              char buf[LENGTH_OF_LINE + 1];            
              char *prp;
              
              rc = JK_TRUE;
  
              while(NULL != (prp = fgets(buf, LENGTH_OF_LINE, fp))) {
                  trim_prp_comment(prp);
                  if(trim(prp)) {
                      char *v = strchr(prp, '=');
                      if(v) {
                          *v = '\0';
                          v++;                        
                          if(strlen(v) && strlen(prp)) {
                              char *oldv = map_get_string(m, prp, NULL);
                              v = map_replace_properties(v, m);
                              if(oldv) {
                                  char *tmpv = jk_pool_alloc(&m->p, 
                                                             strlen(v) + strlen(oldv) + 3);
                                  if(tmpv) {
                                      char sep = '*';
                                      if(jk_is_path_poperty(prp)) {
                                          sep = PATH_SEPERATOR;
                                      } else if(jk_is_cmd_line_poperty(prp)) {
                                          sep = ' ';
                                      }
  
                                      sprintf(tmpv, "%s%c%s", 
                                              oldv, sep, v);
                                  }                                
                                  v = tmpv;
                              } else {
                                  v = jk_pool_strdup(&m->p, v);
                              }
                              if(v) {
                                  void *old = NULL;
                                  map_put(m, prp, v, &old);
                              } else {
                                  rc = JK_FALSE;
                                  break;
                              }
                          }
                      }
                  }
              }
              
              fclose(fp);
          }
      }
  
      return rc;
  }
  
  
  int map_size(jk_map_t *m)
  {
      if(m) {
          return m->size;
      }
  
      return -1;
  }
  
  char *map_name_at(jk_map_t *m,
                    int idex)
  {
      if(m && idex >= 0) {
          return (char *)m->names[idex]; /* DIRTY */
      }
  
      return NULL;
  }
  
  void *map_value_at(jk_map_t *m,
                     int idex)
  {
      if(m && idex >= 0) {
          return (void *) m->values[idex]; /* DIRTY */
      }
  
      return NULL;
  }
  
  static void trim_prp_comment(char *prp)
  {
      char *comment = strchr(prp, '#');
      if(comment) {
          *comment = '\0';
      }
  }
  
  static int trim(char *s)
  {
      int i;
  
      for(i = strlen(s) - 1 ; (i >= 0) && isspace(s[i]) ;  i--)
          ;
      
      s[i + 1] = '\0';
      
      for(i = 0 ; ('\0' !=  s[i]) && isspace(s[i]) ; i++)
          ;
      
      if(i > 0) {
          strcpy(s, &s[i]);
      }
  
      return strlen(s);
  }
  
  static int map_realloc(jk_map_t *m)
  {
      if(m->size == m->capacity) {
          char **names;
          void **values;
          int  capacity = m->capacity + CAPACITY_INC_SIZE;
  
          names = (char **)jk_pool_alloc(&m->p, sizeof(char *) * capacity);
          values = (void **)jk_pool_alloc(&m->p, sizeof(void *) * capacity);
          
          if(values && names) {
              if (m->capacity && m->names) 
                  memcpy(names, m->names, sizeof(char *) * m->capacity);
  
              if (m->capacity && m->values)
                  memcpy(values, m->values, sizeof(void *) * m->capacity);
  
              m->names = (const char **)names;
              m->values = (const void **)values;
              m->capacity = capacity;
  
              return JK_TRUE;
          }
      }
  
      return JK_FALSE;
  }
  
  /**
   *  Replace $(property) in value.
   * 
   */
  char *map_replace_properties(const char *value, jk_map_t *m)
  {
      char *rc = (char *)value;
      char *env_start = rc;
      int rec = 0;
  
      while(env_start = strstr(env_start, "$(")) {
          char *env_end = strstr(env_start, ")");
          if( rec++ > 20 ) return rc;
          if(env_end) {
              char env_name[LENGTH_OF_LINE + 1] = ""; 
              char *env_value;
  
              *env_end = '\0';
              strcpy(env_name, env_start + 2);
              *env_end = ')';
  
              env_value = map_get_string(m, env_name, NULL);
  	    if(!env_value) {
  	      env_value=getenv( env_name );
  	    }
              if(env_value) {
                  int offset=0;
                  char *new_value = jk_pool_alloc(&m->p, 
                                                  (sizeof(char) * (strlen(rc) + strlen(env_value))));
                  if(!new_value) {
                      break;
                  }
                  *env_start = '\0';
                  strcpy(new_value, rc);
                  strcat(new_value, env_value);
                  strcat(new_value, env_end + 1);
  		offset= env_start - rc + strlen( env_value );
                  rc = new_value;
  		/* Avoid recursive subst */
                  env_start = rc + offset; 
              } else {
                  env_start = env_end;
              }
          } else {
              break;
          }
      }
  
      return rc;
  }
  
  
  /** Get a string property, using the worker's style
      for properties.
      Example worker.ajp13.host=localhost.
  */
  char *map_getStrProp(jk_map_t *m,
                       const char *objType,
                       const char *objName,
                       const char *pname,
                       const char *def)
  {
      char buf[1024];
  
      if( m==NULL ||
          objType==NULL ||
          objName==NULL ||
          pname==NULL ) {
          return def;
      }
  
      sprintf(buf, "%s.%s.%s", objType, objName, pname);
      return map_get_string(m, buf, NULL);
  }
  
  int map_getIntProp(jk_map_t *m,
                     const char *objType,
                     const char *objName,
                     const char *pname,
                     const int def)
  {
      char buf[1024];
  
      if( m==NULL ||
          objType==NULL ||
          objName==NULL ||
          pname==NULL ) {
          return def;
      }
  
      sprintf(buf, "%s.%s.%s", objType, objName, pname);
      return map_get_int(m, buf, def);
  }
  
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/common/jk_md5.c
  
  Index: jk_md5.c
  ===================================================================
  /*
   * This is work is derived from material Copyright RSA Data Security, Inc.
   *
   * The RSA copyright statement and Licence for that original material is
   * included below. This is followed by the Apache copyright statement and
   * licence for the modifications made to that material.
   */
  
  /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
   */
  
  /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
     rights reserved.
  
     License to copy and use this software is granted provided that it
     is identified as the "RSA Data Security, Inc. MD5 Message-Digest
     Algorithm" in all material mentioning or referencing this software
     or this function.
  
     License is also granted to make and use derivative works provided
     that such works are identified as "derived from the RSA Data
     Security, Inc. MD5 Message-Digest Algorithm" in all material
     mentioning or referencing the derived work.
  
     RSA Data Security, Inc. makes no representations concerning either
     the merchantability of this software or the suitability of this
     software for any particular purpose. It is provided "as is"
     without express or implied warranty of any kind.
  
     These notices must be retained in any copies of any part of this
     documentation and/or software.
   */
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * Portions of this software are based upon public domain software
   * originally written at the National Center for Supercomputing Applications,
   * University of Illinois, Urbana-Champaign.
   */
  
  /*
   * The ap_MD5Encode() routine uses much code obtained from the FreeBSD 3.0
   * MD5 crypt() function, which is licenced as follows:
   * ----------------------------------------------------------------------------
   * "THE BEER-WARE LICENSE" (Revision 42):
   * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
   * can do whatever you want with this stuff. If we meet some day, and you think
   * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
   * ----------------------------------------------------------------------------
   */
  
  /***************************************************************************
   * Description: MD5 encoding wrapper                                       *
   * Author:      Henri Gomez <hgomez@slib.fr>                               *
   * Version:     $Revision: 1.1 $                                           *
   ***************************************************************************/
  
  /*
   * JK MD5 Encoding function (jk_MD5Encode)
   *
   * Jk delegate MD5 encoding to ap_MD5Encode when used in Apache Web-Server.
   * When another web-server is used like NES/IIS, we should use corresponding calls.
   * NES/IIS specialists will add the necessary code but until that, I reused the code
   * from Apache HTTP server.
   * 
   * Nota: If you use an EBCDIC system without Apache, you'll have to use MD5 encoding
   * corresponding call or have a ebcdic2ascii() functions somewhere.
   * For example current AS/400 have MD5 encoding support APIs but olders not....
   */
   
  #include "jk_global.h"
  #include "jk_md5.h"
  
  char * JK_METHOD jk_hextocstr(unsigned char *org, char * dst, int n)
  {
      char * os = dst;
      unsigned char v;
      static unsigned char zitohex[] = "0123456789ABCDEF";
  
      while (--n >= 0) {
      v = *org++;
      *dst++ = zitohex[v >> 4];
      *dst++ = zitohex[v&0x0f];
      }
      *dst = 0;
  
      return (os);
  }
  
  #ifndef USE_APACHE_MD5 
  
  /* Constants for MD5Transform routine.
   */
  
  #define S11 7
  #define S12 12
  #define S13 17
  #define S14 22
  #define S21 5
  #define S22 9
  #define S23 14
  #define S24 20
  #define S31 4
  #define S32 11
  #define S33 16
  #define S34 23
  #define S41 6
  #define S42 10
  #define S43 15
  #define S44 21
  
  static void MD5Transform(JK_UINT4 state[4], const unsigned char block[64]);
  static void Encode(unsigned char *output, const JK_UINT4 *input, unsigned int len);
  static void Decode(JK_UINT4 *output, const unsigned char *input, unsigned int len);
  static void jk_MD5Init(JK_MD5_CTX *context);
  static void jk_MD5Update(JK_MD5_CTX *context, const unsigned char *input, unsigned int inputLen);
  /*static void jk_MD5Final(unsigned char digest[JK_MD5_DIGESTSIZE], JK_MD5_CTX *context);*/
  
  static unsigned char PADDING[64] =
  {
      0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  };
  
  /* F, G, H and I are basic MD5 functions.
   */
  #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
  #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
  #define H(x, y, z) ((x) ^ (y) ^ (z))
  #define I(x, y, z) ((y) ^ ((x) | (~z)))
  
  /* ROTATE_LEFT rotates x left n bits.
   */
  #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
  
  /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
     Rotation is separate from addition to prevent recomputation.
   */
  #define FF(a, b, c, d, x, s, ac) { \
   (a) += F ((b), (c), (d)) + (x) + (JK_UINT4)(ac); \
   (a) = ROTATE_LEFT ((a), (s)); \
   (a) += (b); \
    }
  #define GG(a, b, c, d, x, s, ac) { \
   (a) += G ((b), (c), (d)) + (x) + (JK_UINT4)(ac); \
   (a) = ROTATE_LEFT ((a), (s)); \
   (a) += (b); \
    }
  #define HH(a, b, c, d, x, s, ac) { \
   (a) += H ((b), (c), (d)) + (x) + (JK_UINT4)(ac); \
   (a) = ROTATE_LEFT ((a), (s)); \
   (a) += (b); \
    }
  #define II(a, b, c, d, x, s, ac) { \
   (a) += I ((b), (c), (d)) + (x) + (JK_UINT4)(ac); \
   (a) = ROTATE_LEFT ((a), (s)); \
   (a) += (b); \
    }
  
  /* MD5 initialization. Begins an MD5 operation, writing a new context.
   */
  static void jk_MD5Init(JK_MD5_CTX *context)
  {
      context->count[0] = context->count[1] = 0;
      /* Load magic initialization constants. */
      context->state[0] = 0x67452301;
      context->state[1] = 0xefcdab89;
      context->state[2] = 0x98badcfe;
      context->state[3] = 0x10325476;
  }
  
  /* MD5 block update operation. Continues an MD5 message-digest
     operation, processing another message block, and updating the
     context.
   */
  static void jk_MD5Update(JK_MD5_CTX *context, const unsigned char *input,
  			      unsigned int inputLen)
  {
      unsigned int i, idx, partLen;
  
      /* Compute number of bytes mod 64 */
      idx = (unsigned int) ((context->count[0] >> 3) & 0x3F);
  
      /* Update number of bits */
      if ((context->count[0] += ((JK_UINT4) inputLen << 3))
  	< ((JK_UINT4) inputLen << 3)) {
  	context->count[1]++;
      }
      context->count[1] += (JK_UINT4) inputLen >> 29;
  
      partLen = 64 - idx;
  
      /* Transform as many times as possible. */
  #ifndef CHARSET_EBCDIC
      if (inputLen >= partLen) {
  	memcpy(&context->buffer[idx], input, partLen);
  	MD5Transform(context->state, context->buffer);
  
  	for (i = partLen; i + 63 < inputLen; i += 64) {
  	    MD5Transform(context->state, &input[i]);
  	}
  
  	idx = 0;
      }
      else {
  	i = 0;
      }
  
      /* Buffer remaining input */
      memcpy(&context->buffer[idx], &input[i], inputLen - i);
  #else /*CHARSET_EBCDIC*/
      if (inputLen >= partLen) {
  	ebcdic2ascii(&context->buffer[idx], input, partLen);
  	MD5Transform(context->state, context->buffer);
  
  	for (i = partLen; i + 63 < inputLen; i += 64) {
  	    unsigned char inp_tmp[64];
  	    ebcdic2ascii(inp_tmp, &input[i], 64);
  	    MD5Transform(context->state, inp_tmp);
  	}
  
  	idx = 0;
      }
      else {
  	i = 0;
      }
  
      /* Buffer remaining input */
      ebcdic2ascii(&context->buffer[idx], &input[i], inputLen - i);
  #endif /*CHARSET_EBCDIC*/
  }
  
  /* MD5 finalization. Ends an MD5 message-digest operation, writing the
     the message digest and zeroizing the context.
   */
  void JK_METHOD jk_MD5Final(unsigned char digest[16], JK_MD5_CTX *context)
  {
      unsigned char bits[8];
      unsigned int idx, padLen;
  
  
      /* Save number of bits */
      Encode(bits, context->count, 8);
  
  #ifdef CHARSET_EBCDIC
      /* XXX: @@@: In order to make this no more complex than necessary,
       * this kludge converts the bits[] array using the ascii-to-ebcdic
       * table, because the following jk_MD5Update() re-translates
       * its input (ebcdic-to-ascii).
       * Otherwise, we would have to pass a "conversion" flag to jk_MD5Update()
       */
      ascii2ebcdic(bits,bits,8);
  
      /* Since everything is converted to ascii within jk_MD5Update(), 
       * the initial 0x80 (PADDING[0]) must be stored as 0x20 
       */
      ascii2ebcdic(PADDING,PADDING,1);
  #endif /*CHARSET_EBCDIC*/
  
      /* Pad out to 56 mod 64. */
      idx = (unsigned int) ((context->count[0] >> 3) & 0x3f);
      padLen = (idx < 56) ? (56 - idx) : (120 - idx);
      jk_MD5Update(context, (const unsigned char *)PADDING, padLen);
  
      /* Append length (before padding) */
      jk_MD5Update(context, (const unsigned char *)bits, 8);
  
      /* Store state in digest */
      Encode(digest, context->state, 16);
  
      /* Zeroize sensitive information. */
      memset(context, 0, sizeof(*context));
  }
  
  /* MD5 basic transformation. Transforms state based on block. */
  static void MD5Transform(JK_UINT4 state[4], const unsigned char block[64])
  {
      JK_UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
  
      Decode(x, block, 64);
  
      /* Round 1 */
      FF(a, b, c, d, x[0], S11, 0xd76aa478);	/* 1 */
      FF(d, a, b, c, x[1], S12, 0xe8c7b756);	/* 2 */
      FF(c, d, a, b, x[2], S13, 0x242070db);	/* 3 */
      FF(b, c, d, a, x[3], S14, 0xc1bdceee);	/* 4 */
      FF(a, b, c, d, x[4], S11, 0xf57c0faf);	/* 5 */
      FF(d, a, b, c, x[5], S12, 0x4787c62a);	/* 6 */
      FF(c, d, a, b, x[6], S13, 0xa8304613);	/* 7 */
      FF(b, c, d, a, x[7], S14, 0xfd469501);	/* 8 */
      FF(a, b, c, d, x[8], S11, 0x698098d8);	/* 9 */
      FF(d, a, b, c, x[9], S12, 0x8b44f7af);	/* 10 */
      FF(c, d, a, b, x[10], S13, 0xffff5bb1);	/* 11 */
      FF(b, c, d, a, x[11], S14, 0x895cd7be);	/* 12 */
      FF(a, b, c, d, x[12], S11, 0x6b901122);	/* 13 */
      FF(d, a, b, c, x[13], S12, 0xfd987193);	/* 14 */
      FF(c, d, a, b, x[14], S13, 0xa679438e);	/* 15 */
      FF(b, c, d, a, x[15], S14, 0x49b40821);	/* 16 */
  
      /* Round 2 */
      GG(a, b, c, d, x[1], S21, 0xf61e2562);	/* 17 */
      GG(d, a, b, c, x[6], S22, 0xc040b340);	/* 18 */
      GG(c, d, a, b, x[11], S23, 0x265e5a51);	/* 19 */
      GG(b, c, d, a, x[0], S24, 0xe9b6c7aa);	/* 20 */
      GG(a, b, c, d, x[5], S21, 0xd62f105d);	/* 21 */
      GG(d, a, b, c, x[10], S22, 0x2441453);	/* 22 */
      GG(c, d, a, b, x[15], S23, 0xd8a1e681);	/* 23 */
      GG(b, c, d, a, x[4], S24, 0xe7d3fbc8);	/* 24 */
      GG(a, b, c, d, x[9], S21, 0x21e1cde6);	/* 25 */
      GG(d, a, b, c, x[14], S22, 0xc33707d6);	/* 26 */
      GG(c, d, a, b, x[3], S23, 0xf4d50d87);	/* 27 */
      GG(b, c, d, a, x[8], S24, 0x455a14ed);	/* 28 */
      GG(a, b, c, d, x[13], S21, 0xa9e3e905);	/* 29 */
      GG(d, a, b, c, x[2], S22, 0xfcefa3f8);	/* 30 */
      GG(c, d, a, b, x[7], S23, 0x676f02d9);	/* 31 */
      GG(b, c, d, a, x[12], S24, 0x8d2a4c8a);	/* 32 */
  
      /* Round 3 */
      HH(a, b, c, d, x[5], S31, 0xfffa3942);	/* 33 */
      HH(d, a, b, c, x[8], S32, 0x8771f681);	/* 34 */
      HH(c, d, a, b, x[11], S33, 0x6d9d6122);	/* 35 */
      HH(b, c, d, a, x[14], S34, 0xfde5380c);	/* 36 */
      HH(a, b, c, d, x[1], S31, 0xa4beea44);	/* 37 */
      HH(d, a, b, c, x[4], S32, 0x4bdecfa9);	/* 38 */
      HH(c, d, a, b, x[7], S33, 0xf6bb4b60);	/* 39 */
      HH(b, c, d, a, x[10], S34, 0xbebfbc70);	/* 40 */
      HH(a, b, c, d, x[13], S31, 0x289b7ec6);	/* 41 */
      HH(d, a, b, c, x[0], S32, 0xeaa127fa);	/* 42 */
      HH(c, d, a, b, x[3], S33, 0xd4ef3085);	/* 43 */
      HH(b, c, d, a, x[6], S34, 0x4881d05);	/* 44 */
      HH(a, b, c, d, x[9], S31, 0xd9d4d039);	/* 45 */
      HH(d, a, b, c, x[12], S32, 0xe6db99e5);	/* 46 */
      HH(c, d, a, b, x[15], S33, 0x1fa27cf8);	/* 47 */
      HH(b, c, d, a, x[2], S34, 0xc4ac5665);	/* 48 */
  
      /* Round 4 */
      II(a, b, c, d, x[0], S41, 0xf4292244);	/* 49 */
      II(d, a, b, c, x[7], S42, 0x432aff97);	/* 50 */
      II(c, d, a, b, x[14], S43, 0xab9423a7);	/* 51 */
      II(b, c, d, a, x[5], S44, 0xfc93a039);	/* 52 */
      II(a, b, c, d, x[12], S41, 0x655b59c3);	/* 53 */
      II(d, a, b, c, x[3], S42, 0x8f0ccc92);	/* 54 */
      II(c, d, a, b, x[10], S43, 0xffeff47d);	/* 55 */
      II(b, c, d, a, x[1], S44, 0x85845dd1);	/* 56 */
      II(a, b, c, d, x[8], S41, 0x6fa87e4f);	/* 57 */
      II(d, a, b, c, x[15], S42, 0xfe2ce6e0);	/* 58 */
      II(c, d, a, b, x[6], S43, 0xa3014314);	/* 59 */
      II(b, c, d, a, x[13], S44, 0x4e0811a1);	/* 60 */
      II(a, b, c, d, x[4], S41, 0xf7537e82);	/* 61 */
      II(d, a, b, c, x[11], S42, 0xbd3af235);	/* 62 */
      II(c, d, a, b, x[2], S43, 0x2ad7d2bb);	/* 63 */
      II(b, c, d, a, x[9], S44, 0xeb86d391);	/* 64 */
  
      state[0] += a;
      state[1] += b;
      state[2] += c;
      state[3] += d;
  
      /* Zeroize sensitive information. */
      memset(x, 0, sizeof(x));
  }
  
  /* Encodes input (JK_UINT4) into output (unsigned char). Assumes len is
     a multiple of 4.
   */
  static void Encode(unsigned char *output, const JK_UINT4 *input, unsigned int len)
  {
      unsigned int i, j;
      JK_UINT4 k;
  
      for (i = 0, j = 0; j < len; i++, j += 4) {
  	k = input[i];
  	output[j] = (unsigned char) (k & 0xff);
  	output[j + 1] = (unsigned char) ((k >> 8) & 0xff);
  	output[j + 2] = (unsigned char) ((k >> 16) & 0xff);
  	output[j + 3] = (unsigned char) ((k >> 24) & 0xff);
      }
  }
  
  /* Decodes input (unsigned char) into output (JK_UINT4). Assumes len is
   * a multiple of 4.
   */
  static void Decode(JK_UINT4 *output, const unsigned char *input, unsigned int len)
  {
      unsigned int i, j;
  
      for (i = 0, j = 0; j < len; i++, j += 4)
  	output[i] = ((JK_UINT4) input[j]) | (((JK_UINT4) input[j + 1]) << 8) |
  	    (((JK_UINT4) input[j + 2]) << 16) | (((JK_UINT4) input[j + 3]) << 24);
  }
  
  /*
   * The following MD5 password encryption code was largely borrowed from
   * the FreeBSD 3.0 /usr/src/lib/libcrypt/crypt.c file, which is
   * licenced as stated at the top of this file.
   */
  static void jk_to64(char *s, unsigned long v, int n)
  {
      static unsigned char itoa64[] =         /* 0 ... 63 => ASCII - 64 */
  	"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  
      while (--n >= 0) {
  	*s++ = itoa64[v&0x3f];
  	v >>= 6;
      }
  }
  
  char * JK_METHOD jk_md5(const unsigned char *org, const unsigned char *org2, char *dst)
  {
  	JK_MD5_CTX  ctx;
  	char		buf[JK_MD5_DIGESTSIZE + 1];
  
      jk_MD5Init(&ctx);
      jk_MD5Update(&ctx, org, strlen((const char *)org));
  
  	if (org2 != NULL)
  		jk_MD5Update(&ctx, org2, strlen((const char *)org2));
  
      jk_MD5Final((unsigned char *)buf, &ctx);
  	return (jk_hextocstr((unsigned char *)buf, dst, JK_MD5_DIGESTSIZE));
  }
  
  #else /* USE_APACHE_MD5 */
  
  #include "httpd.h"
  #include "http_config.h"
  
  #ifdef STANDARD20_MODULE_STUFF
  
  #include "apr_md5.h"
  #define  AP_MD5_CTX 	apr_md5_ctx_t
  #define  ap_MD5Init 	apr_md5_init
  #define  ap_MD5Update 	apr_md5_update
  #define  ap_MD5Final 	apr_md5_final
  
  #else /* STANDARD20_MODULE_STUFF */
  
  #include "ap_md5.h"
  
  #endif /* STANDARD20_MODULE_STUFF */
  
  char * JK_METHOD jk_md5(const unsigned char *org, const unsigned char *org2, char *dst)
  {
  	AP_MD5_CTX ctx;
  	char	   buf[JK_MD5_DIGESTSIZE + 1];
  
      ap_MD5Init(&ctx);
      ap_MD5Update(&ctx, org, strlen(org));
  
  	if (org2 != NULL)
  		ap_MD5Update(&ctx, org2, strlen(org2));
  
      ap_MD5Final(buf, &ctx);
  	return (jk_hextocstr(buf, dst, JK_MD5_DIGESTSIZE));
  }
  
  #endif /* USE_APACHE_MD5 */
  
  /* Test values:
   * ""                  D4 1D 8C D9 8F 00 B2 04  E9 80 09 98 EC F8 42 7E
   * "a"                 0C C1 75 B9 C0 F1 B6 A8  31 C3 99 E2 69 77 26 61
   * "abc                90 01 50 98 3C D2 4F B0  D6 96 3F 7D 28 E1 7F 72
   * "message digest"    F9 6B 69 7D 7C B7 93 8D  52 5A 2F 31 AA F1 61 D0
   *
   */
  
  #ifdef TEST_JKMD5
  
  main(int argc, char ** argv)
  {
  	char xxx[(2 * JK_MD5_DIGESTSIZE) + 1];
  
  	if (argc > 1)
  		printf("%s => %s\n", argv[1], jk_md5(argv[1], NULL, xxx));
  }
  
  #endif 
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/common/jk_msg_buff.c
  
  Index: jk_msg_buff.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 The Apache Software License,  Version 1.1                 *
   *                                                                           *
   *          Copyright (c) 1999-2001 The Apache Software Foundation.          *
   *                           All rights reserved.                            *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * Redistribution and use in source and binary forms,  with or without modi- *
   * fication, are permitted provided that the following conditions are met:   *
   *                                                                           *
   * 1. Redistributions of source code  must retain the above copyright notice *
   *    notice, this list of conditions and the following disclaimer.          *
   *                                                                           *
   * 2. Redistributions  in binary  form  must  reproduce the  above copyright *
   *    notice,  this list of conditions  and the following  disclaimer in the *
   *    documentation and/or other materials provided with the distribution.   *
   *                                                                           *
   * 3. The end-user documentation  included with the redistribution,  if any, *
   *    must include the following acknowlegement:                             *
   *                                                                           *
   *       "This product includes  software developed  by the Apache  Software *
   *        Foundation <http://www.apache.org/>."                              *
   *                                                                           *
   *    Alternately, this acknowlegement may appear in the software itself, if *
   *    and wherever such third-party acknowlegements normally appear.         *
   *                                                                           *
   * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software     *
   *    Foundation"  must not be used  to endorse or promote  products derived *
   *    from this  software without  prior  written  permission.  For  written *
   *    permission, please contact <apache@apache.org>.                        *
   *                                                                           *
   * 5. Products derived from this software may not be called "Apache" nor may *
   *    "Apache" appear in their names without prior written permission of the *
   *    Apache Software Foundation.                                            *
   *                                                                           *
   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
   * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY *
   * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL *
   * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY *
   * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL *
   * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS *
   * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) *
   * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT, *
   * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
   * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE *
   * POSSIBILITY OF SUCH DAMAGE.                                               *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * This software  consists of voluntary  contributions made  by many indivi- *
   * duals on behalf of the  Apache Software Foundation.  For more information *
   * on the Apache Software Foundation, please see <http://www.apache.org/>.   *
   *                                                                           *
   * ========================================================================= */
  
  /***************************************************************************
   * Description: Data marshaling. XDR like                                  *
   * Author:      Costin <costin@costin.dnt.ro>                              *
   * Author:      Gal Shachor <shachor@il.ibm.com>                           *
   * Author:      Henri Gomez <hgomez@slib.fr>                               *
   * Version:     $Revision: 1.1 $                                           *
   ***************************************************************************/
  
  #include "jk_pool.h"
  #include "jk_util.h"
  #include "jk_msg_buff.h"
  #include "jk_logger.h"
  
  struct jk_msg_buf {
      jk_pool_t *pool;
  
      unsigned char *buf;
      int pos; 
      int len;
      int maxlen;
  };
  
  
  /*
   * Simple marshaling code.
   */
  
  /* XXX what's above this line can go to .h XXX */
  void jk_b_dump(jk_msg_buf_t *msg, 
                 char *err) 
  {
      int i=0;
  	printf("%s %d/%d/%d %x %x %x %x - %x %x %x %x - %x %x %x %x - %x %x %x %x\n", err, msg->pos, msg->len, msg->maxlen,  
  	       msg->buf[i++],msg->buf[i++],msg->buf[i++],msg->buf[i++],
  	       msg->buf[i++],msg->buf[i++],msg->buf[i++],msg->buf[i++],
  	       msg->buf[i++],msg->buf[i++],msg->buf[i++],msg->buf[i++],
  	       msg->buf[i++],msg->buf[i++],msg->buf[i++],msg->buf[i++]);
  
  	i = msg->pos - 4;
      if(i < 0) {
          i=0;
      }
  	
      printf("        %x %x %x %x - %x %x %x %x --- %x %x %x %x - %x %x %x %x\n", 
  	       msg->buf[i++],msg->buf[i++],msg->buf[i++],msg->buf[i++],
  	       msg->buf[i++],msg->buf[i++],msg->buf[i++],msg->buf[i++],
  	       msg->buf[i++],msg->buf[i++],msg->buf[i++],msg->buf[i++],
  	       msg->buf[i++],msg->buf[i++],msg->buf[i++],msg->buf[i++]);
  
  }
  
  void jk_b_reset(jk_msg_buf_t *msg) 
  {
      msg->len = 4;
      msg->pos = 4;
  }
  
  
  static void jk_b_set_long(jk_msg_buf_t *msg,
                    int pos,
                    unsigned long val)
  {   
      msg->buf[pos]       = (unsigned char)((val >> 24) & 0xFF);
      msg->buf[pos + 1]   = (unsigned char)((val >> 16) & 0xFF);
      msg->buf[pos + 2]   = (unsigned char)((val >> 8) & 0xFF);
      msg->buf[pos + 3]   = (unsigned char)(val & 0xFF);
  }
  
  
  int jk_b_append_long(jk_msg_buf_t *msg,
                      unsigned long val)
  {
      if(msg->len + 4 > msg->maxlen) {
          return -1;
      }
  
      jk_b_set_long(msg, msg->len, val);
  
      msg->len += 4;
  
      return 0;
  }
  
  
  static void jk_b_set_int(jk_msg_buf_t *msg, 
                    int pos, 
                    unsigned short val) 
  {
      msg->buf[pos]       = (unsigned char)((val >> 8) & 0xFF);
      msg->buf[pos + 1]   = (unsigned char)(val & 0xFF);
  }
  
  
  int jk_b_append_int(jk_msg_buf_t *msg, 
                      unsigned short val) 
  {
      if(msg->len + 2 > msg->maxlen) {
  	    return -1;
      }
  
      jk_b_set_int(msg, msg->len, val);
  
      msg->len += 2;
  
      return 0;
  }
  
  
  static void jk_b_set_byte(jk_msg_buf_t *msg, 
                     int pos, 
                     unsigned char val) 
  {
      msg->buf[pos]= val;
  }
  
  int jk_b_append_byte(jk_msg_buf_t *msg, 
                       unsigned char val)
  {
      if(msg->len + 1 > msg->maxlen) {
  	    return -1;
      }
  
      jk_b_set_byte(msg, msg->len, val);
  
      msg->len += 1;
  
      return 0;
  }
  
  
  void jk_b_end(jk_msg_buf_t *msg, int protoh) 
  {
      /* 
       * Ugly way to set the size in the right position 
       */
      jk_b_set_int(msg, 2, (unsigned short )(msg->len - 4)); /* see protocol */
      jk_b_set_int(msg, 0, (unsigned short) protoh);
  }
  
  
  jk_msg_buf_t *jk_b_new(jk_pool_t *p) 
  {
      jk_msg_buf_t *msg = 
              (jk_msg_buf_t *)jk_pool_alloc(p, sizeof(jk_msg_buf_t));
  
      if(!msg) {
          return NULL;
      }
  
      msg->pool = p;
      
      return msg;
  }
  
  int jk_b_set_buffer(jk_msg_buf_t *msg, 
                      char *data, 
                      int buffSize) 
  {
      if(!msg) {
          return -1;
      }
  
      msg->len = 0;
      msg->buf = (unsigned char *)data;
      msg->maxlen = buffSize;
      
      return 0;
  }
  
  
  int jk_b_set_buffer_size(jk_msg_buf_t *msg, 
                           int buffSize) 
  {
      unsigned char *data = (unsigned char *)jk_pool_alloc(msg->pool, buffSize);
      
      if(!data) {
  	    return -1;
      }
  
      jk_b_set_buffer(msg, (char *)data, buffSize);
      return 0;
  }
  
  unsigned char *jk_b_get_buff(jk_msg_buf_t *msg) 
  {
      return msg->buf;
  }
  
  unsigned int jk_b_get_pos(jk_msg_buf_t *msg) 
  {
      return msg->pos;
  }
  
  void jk_b_set_pos(jk_msg_buf_t *msg,
                            int pos) 
  {
      msg->pos = pos;
  }
  
  unsigned int jk_b_get_len(jk_msg_buf_t *msg) 
  {
      return msg->len;
  }
  
  void jk_b_set_len(jk_msg_buf_t *msg, 
                    int len) 
  {
      msg->len=len;
  }
  
  int jk_b_get_size(jk_msg_buf_t *msg) 
  {
      return msg->maxlen;
  }
  
  int jk_b_append_string(jk_msg_buf_t *msg, 
                         const char *param) 
  {
      int len;
  
      if(!param) {
  	    jk_b_append_int( msg, 0xFFFF );
  	    return 0; 
      }
  
      len = strlen(param);
      if(msg->len + len + 2  > msg->maxlen) {
  	    return -1;
      }
  
      /* ignore error - we checked once */
      jk_b_append_int(msg, (unsigned short )len);
  
      /* We checked for space !!  */
      strncpy((char *)msg->buf + msg->len , param, len+1);    /* including \0 */
      jk_xlate_to_ascii((char *)msg->buf + msg->len, len+1);  /* convert from EBCDIC if needed */
      msg->len += len + 1;
  
      return 0;
  }
  
  
  int jk_b_append_bytes(jk_msg_buf_t         *msg,
                        const unsigned char  *param,
  					  int                   len)
  {
      if (! len) {
          return 0;
      }
  
      if (msg->len + len > msg->maxlen) {
          return -1;
      }
  
      /* We checked for space !!  */
      memcpy((char *)msg->buf + msg->len, param, len); 
      msg->len += len;
  
      return 0;
  }
  
  unsigned long jk_b_get_long(jk_msg_buf_t *msg)
  {
      unsigned long i;
      if(msg->pos + 3 > msg->len) {
          printf( "Read after end \n");
          return -1;
      }
      i  = ((msg->buf[(msg->pos++)] & 0xFF)<<24);
      i |= ((msg->buf[(msg->pos++)] & 0xFF)<<16);
      i |= ((msg->buf[(msg->pos++)] & 0xFF)<<8);
      i |= ((msg->buf[(msg->pos++)] & 0xFF));
      return i;
  }
  
  unsigned long jk_b_pget_long(jk_msg_buf_t *msg,
                               int pos)
  {
      unsigned long i;
      i  = ((msg->buf[(pos++)] & 0xFF)<<24);
      i |= ((msg->buf[(pos++)] & 0xFF)<<16);
      i |= ((msg->buf[(pos++)] & 0xFF)<<8);
      i |= ((msg->buf[(pos  )] & 0xFF));
      return i;
  }
  
  
  unsigned short jk_b_get_int(jk_msg_buf_t *msg) 
  {
      int i;
      if(msg->pos + 1 > msg->len) {
  	    printf( "Read after end \n");
  	    return -1;
      }
      i  = ((msg->buf[(msg->pos++)] & 0xFF)<<8);
      i += ((msg->buf[(msg->pos++)] & 0xFF));
      return i;
  }
  
  unsigned short jk_b_pget_int(jk_msg_buf_t *msg, 
                               int pos) 
  {
      int i;
  	i  = ((msg->buf[pos++] & 0xFF)<<8);
      i += ((msg->buf[pos]   & 0xFF));
      return i;
  }
  
  unsigned char jk_b_get_byte(jk_msg_buf_t *msg) 
  {
      unsigned char rc;
      if(msg->pos > msg->len) {
  	    printf("Read after end \n");
  	    return -1;
      }
      rc = msg->buf[msg->pos++];
      
      return rc;
  }
  
  unsigned char jk_b_pget_byte(jk_msg_buf_t *msg, 
                               int pos) 
  {
      return msg->buf[pos];
  }
  
  
  unsigned char *jk_b_get_string(jk_msg_buf_t *msg) 
  {
      int size = jk_b_get_int(msg);
      int start = msg->pos;
  
      if((size < 0 ) || (size + start > msg->maxlen)) { 
  	    jk_b_dump(msg, "After get int"); 
  	    printf("ERROR\n" );
  	    return (unsigned char *)"ERROR"; /* XXX */
      }
  
      msg->pos += size;
      msg->pos++;  /* terminating NULL */
      
      return (unsigned char *)(msg->buf + start); 
  }
  
  int jk_b_get_bytes(jk_msg_buf_t *msg, unsigned char * buf, int len)
  {
      int start = msg->pos;
  
      if((len < 0 ) || (len + start > msg->maxlen)) {
          jk_b_dump(msg, "After get bytes");
          printf("ERROR\n" ); 
          return (-1);
      }
      
  	memcpy(buf, msg->buf + start, len);
      msg->pos += len;
  	return (len);
  }
  
  
  /** Shame-less copy from somewhere.
      assert (src != dst)
   */
  static void swap_16(unsigned char *src, unsigned char *dst) 
  {
      *dst++ = *(src + 1 );
      *dst= *src;
  }
  
  /** Helpie dump function 
   */
  void jk_dump_buff(jk_logger_t *l,
                        const char *file,
                        int line,
                        int level,
                        char * what,
                        jk_msg_buf_t * msg)
  {
  #ifdef USE_ALSO_BODY
          jk_log(l, file, line, level, "%s #%d %.*s\n",
                    what,
                    jk_b_get_len(msg),
                    jk_b_get_len(msg),
                    jk_b_get_buff(msg));
  #else
  jk_log(l, file, line, level, "%s #%d\n", what, jk_b_get_len(msg));
  #endif
  }
  
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/common/jk_nwmain.c
  
  Index: jk_nwmain.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 The Apache Software License,  Version 1.1                 *
   *                                                                           *
   *          Copyright (c) 1999-2001 The Apache Software Foundation.          *
   *                           All rights reserved.                            *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * Redistribution and use in source and binary forms,  with or without modi- *
   * fication, are permitted provided that the following conditions are met:   *
   *                                                                           *
   * 1. Redistributions of source code  must retain the above copyright notice *
   *    notice, this list of conditions and the following disclaimer.          *
   *                                                                           *
   * 2. Redistributions  in binary  form  must  reproduce the  above copyright *
   *    notice,  this list of conditions  and the following  disclaimer in the *
   *    documentation and/or other materials provided with the distribution.   *
   *                                                                           *
   * 3. The end-user documentation  included with the redistribution,  if any, *
   *    must include the following acknowlegement:                             *
   *                                                                           *
   *       "This product includes  software developed  by the Apache  Software *
   *        Foundation <http://www.apache.org/>."                              *
   *                                                                           *
   *    Alternately, this acknowlegement may appear in the software itself, if *
   *    and wherever such third-party acknowlegements normally appear.         *
   *                                                                           *
   * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software     *
   *    Foundation"  must not be used  to endorse or promote  products derived *
   *    from this  software without  prior  written  permission.  For  written *
   *    permission, please contact <apache@apache.org>.                        *
   *                                                                           *
   * 5. Products derived from this software may not be called "Apache" nor may *
   *    "Apache" appear in their names without prior written permission of the *
   *    Apache Software Foundation.                                            *
   *                                                                           *
   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
   * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY *
   * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL *
   * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY *
   * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL *
   * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS *
   * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) *
   * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT, *
   * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
   * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE *
   * POSSIBILITY OF SUCH DAMAGE.                                               *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * This software  consists of voluntary  contributions made  by many indivi- *
   * duals on behalf of the  Apache Software Foundation.  For more information *
   * on the Apache Software Foundation, please see <http://www.apache.org/>.   *
   *                                                                           *
   * ========================================================================= */
  
  /***************************************************************************
   * Description: Netware Wrapper                                            *
   * Author:      Mike Anderson <mmander@novell.com>                         *
   * Version:     $Revision: 1.1 $                                           *
   ***************************************************************************/
  
  #ifdef NETWARE
  /*
   * NATIVE_MAIN
   */
  
  /*
   * INCLUDES
   */
  
  #include <stdio.h>
  #include <nwthread.h>
  #include <netdb.h>
  
  NETDB_DEFINE_CONTEXT
  
  /*
   * main ()
   *
   * Main entry point -- don't do much more than I've provided
   *
   * Entry:
   *
   * Exit:
   *    Nothing
   */
  
  void main ()
  {
     ExitThread (TSR_THREAD, 0);
  }
  #endif
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/common/jk_pool.c
  
  Index: jk_pool.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 The Apache Software License,  Version 1.1                 *
   *                                                                           *
   *          Copyright (c) 1999-2001 The Apache Software Foundation.          *
   *                           All rights reserved.                            *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * Redistribution and use in source and binary forms,  with or without modi- *
   * fication, are permitted provided that the following conditions are met:   *
   *                                                                           *
   * 1. Redistributions of source code  must retain the above copyright notice *
   *    notice, this list of conditions and the following disclaimer.          *
   *                                                                           *
   * 2. Redistributions  in binary  form  must  reproduce the  above copyright *
   *    notice,  this list of conditions  and the following  disclaimer in the *
   *    documentation and/or other materials provided with the distribution.   *
   *                                                                           *
   * 3. The end-user documentation  included with the redistribution,  if any, *
   *    must include the following acknowlegement:                             *
   *                                                                           *
   *       "This product includes  software developed  by the Apache  Software *
   *        Foundation <http://www.apache.org/>."                              *
   *                                                                           *
   *    Alternately, this acknowlegement may appear in the software itself, if *
   *    and wherever such third-party acknowlegements normally appear.         *
   *                                                                           *
   * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software     *
   *    Foundation"  must not be used  to endorse or promote  products derived *
   *    from this  software without  prior  written  permission.  For  written *
   *    permission, please contact <apache@apache.org>.                        *
   *                                                                           *
   * 5. Products derived from this software may not be called "Apache" nor may *
   *    "Apache" appear in their names without prior written permission of the *
   *    Apache Software Foundation.                                            *
   *                                                                           *
   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
   * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY *
   * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL *
   * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY *
   * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL *
   * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS *
   * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) *
   * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT, *
   * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
   * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE *
   * POSSIBILITY OF SUCH DAMAGE.                                               *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * This software  consists of voluntary  contributions made  by many indivi- *
   * duals on behalf of the  Apache Software Foundation.  For more information *
   * on the Apache Software Foundation, please see <http://www.apache.org/>.   *
   *                                                                           *
   * ========================================================================= */
  
  /***************************************************************************
   * Description: Simple memory pool                                         *
   * Author:      Gal Shachor <shachor@il.ibm.com>                           *
   * Version:     $Revision: 1.1 $                                           *
   ***************************************************************************/
  
  #include "jk_pool.h"
  #include "jk_env.h"
  
  #define DEFAULT_DYNAMIC 10
  
  
  static void *jk_pool_dyn_alloc(jk_pool_t *p, 
                                 size_t size);
  
  
  void jk_open_pool(jk_pool_t *p,
                    jk_pool_atom_t *buf,
                    unsigned size)
  {
      p->pos  = 0;
      p->size = size;
      p->buf  = (char *)buf;
  
      p->dyn_pos = 0;
      p->dynamic = NULL;
      p->dyn_size = 0;
  }
  
  void jk_close_pool(jk_pool_t *p)
  {
      if(p) {
          jk_reset_pool(p);
          if(p->dynamic) {
              free(p->dynamic);
          }
      }
  }
  
  void jk_reset_pool(jk_pool_t *p)
  {
      if(p && p->dyn_pos && p->dynamic) {
          unsigned i;
          for(i = 0 ; i < p->dyn_pos ; i++) {
              if(p->dynamic[i]) {
                  free(p->dynamic[i]);
              }
          }
      }
  
      p->dyn_pos  = 0;
      p->pos      = 0;
  }
  
  void *jk_pool_alloc(jk_pool_t *p, 
                      size_t size)
  {
      void *rc = NULL;
  
      if(p && size > 0) {
          /* Round size to the upper mult of 8. */
          size -= 1;
          size /= 8;
          size = (size + 1) * 8;
          if((p->size - p->pos) >= size) {
              rc = &(p->buf[p->pos]);
              p->pos += size;
          } else {
              rc = jk_pool_dyn_alloc(p, size);
          }
      }
  
      return rc;
  }
  
  void *jk_pool_realloc(jk_pool_t *p, 
                        size_t sz,
                        const void *old,
                        size_t old_sz)
  {
      void *rc;
  
      if(!p || (!old && old_sz)) {
          return NULL;
      }
  
      rc = jk_pool_alloc(p, sz);
      if(rc) {
          memcpy(rc, old, old_sz);
      }
  
      return rc;
  }
  
  void *jk_pool_strdup(jk_pool_t *p, 
                       const char *s)
  {
      char *rc = NULL;
      if(s && p) {
          size_t size = strlen(s);
      
          if(!size)  {
              return "";
          }
  
          size++;
          rc = jk_pool_alloc(p, size);
          if(rc) {
              memcpy(rc, s, size);
          }
      }
  
      return rc;
  }
  
  void jk_dump_pool(jk_pool_t *p, 
                    FILE *f)
  {
      fprintf(f, "Dumping for pool [%x]\n", p);
      fprintf(f, "size             [%d]\n", p->size);
      fprintf(f, "pos              [%d]\n", p->pos);
      fprintf(f, "buf              [%x]\n", p->buf);  
      fprintf(f, "dyn_size         [%d]\n", p->dyn_size);
      fprintf(f, "dyn_pos          [%d]\n", p->dyn_pos);
      fprintf(f, "dynamic          [%x]\n", p->dynamic);
  
      fflush(f);
  }
  
  static void *jk_pool_dyn_alloc(jk_pool_t *p, 
                                 size_t size)
  {
      void *rc = NULL;
  
      if(p->dyn_size == p->dyn_pos) {
          unsigned new_dyn_size = p->dyn_size + DEFAULT_DYNAMIC;
          void **new_dynamic = (void **)malloc(new_dyn_size * sizeof(void *));
          if(new_dynamic) {
              if(p->dynamic) {
                  memcpy(new_dynamic, 
                         p->dynamic, 
                         p->dyn_size * sizeof(void *));
  
                  free(p->dynamic);
              }
  
              p->dynamic = new_dynamic;
              p->dyn_size = new_dyn_size;
          } else {
              return NULL;
          }
      } 
  
      rc = p->dynamic[p->dyn_pos] = malloc(size);
      if(p->dynamic[p->dyn_pos]) {
          p->dyn_pos ++;
      }
  
      return rc;
  }
  
  int JK_METHOD jk_pool_factory( jk_env_t *env, void **result,
                                 char *type, char *name)
  {
      jk_pool_t *_this=(jk_pool_t *)calloc( 1, sizeof(jk_pool_t));
  
      _this->open=jk_open_pool;
      _this->close=jk_close_pool;
      _this->reset=jk_reset_pool;
      _this->alloc=jk_pool_alloc;
      _this->strdup=jk_pool_strdup;
  
      *result=_this;
      
      return JK_TRUE;
  }
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/common/jk_registry.c
  
  Index: jk_registry.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 The Apache Software License,  Version 1.1                 *
   *                                                                           *
   *          Copyright (c) 1999-2001 The Apache Software Foundation.          *
   *                           All rights reserved.                            *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * Redistribution and use in source and binary forms,  with or without modi- *
   * fication, are permitted provided that the following conditions are met:   *
   *                                                                           *
   * 1. Redistributions of source code  must retain the above copyright notice *
   *    notice, this list of conditions and the following disclaimer.          *
   *                                                                           *
   * 2. Redistributions  in binary  form  must  reproduce the  above copyright *
   *    notice,  this list of conditions  and the following  disclaimer in the *
   *    documentation and/or other materials provided with the distribution.   *
   *                                                                           *
   * 3. The end-user documentation  included with the redistribution,  if any, *
   *    must include the following acknowlegement:                             *
   *                                                                           *
   *       "This product includes  software developed  by the Apache  Software *
   *        Foundation <http://www.apache.org/>."                              *
   *                                                                           *
   *    Alternately, this acknowlegement may appear in the software itself, if *
   *    and wherever such third-party acknowlegements normally appear.         *
   *                                                                           *
   * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software     *
   *    Foundation"  must not be used  to endorse or promote  products derived *
   *    from this  software without  prior  written  permission.  For  written *
   *    permission, please contact <apache@apache.org>.                        *
   *                                                                           *
   * 5. Products derived from this software may not be called "Apache" nor may *
   *    "Apache" appear in their names without prior written permission of the *
   *    Apache Software Foundation.                                            *
   *                                                                           *
   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
   * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY *
   * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL *
   * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY *
   * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL *
   * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS *
   * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) *
   * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT, *
   * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
   * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE *
   * POSSIBILITY OF SUCH DAMAGE.                                               *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * This software  consists of voluntary  contributions made  by many indivi- *
   * duals on behalf of the  Apache Software Foundation.  For more information *
   * on the Apache Software Foundation, please see <http://www.apache.org/>.   *
   *                                                                           *
   * ========================================================================= */
  
  #include "jk_logger.h"
  #include "jk_pool.h"
  #include "jk_service.h"
  #include "jk_env.h"
  
  /***************************************************************************
   * Description: Worker list                                                *
   * Version:     $Revision: 1.1 $                                           *
   ***************************************************************************/
  
  /** Static declarations for all 'hardcoded' modules. This is a hack, 
   *  needed to initialize the static 'type system' for jk. 
   *
   *  A better solution would use 'introspection' and dlsyms to locate the 
   *  factory, using the common naming schema. This is a bit harder to implement
   *  ( we can do it later ) and may have problems on some buggy OSs ( I assume
   *  most decent systems support .so/.dll and symbols, but you can never know )
   * 
   *  Both solutions could be used in paralel - for start we'll use this
   *  hack and static registration. Don't put anything else here, just 
   *  static declarations for the factory methods and the registrerFactory() call.
   * 
   * (based on jk_worker_list.h )
   * @author:      Gal Shachor <shachor@il.ibm.com>                           *
   * @author:      Henri Gomez <hgomez@slib.fr>                               *
   * @author:      Costin Manolache
   *  
   */
  
  int JK_METHOD jk_worker_ajp14_factory( jk_env_t *env, void **result,
                                         char *type, char *name);
  
                                     
  int JK_METHOD jk_worker_lb_factory(jk_env_t *env, void **result,
                                     char *type, char *name);
  
  
  int JK_METHOD jk_worker_jni_factory(jk_env_t *env, void **result,
                                      char *type, char *name);
  
  int JK_METHOD jk_worker_ajp12_factory(jk_env_t *env, void **result,
                                      char *type, char *name);
  
  /* Factories for 'new' types. We use the new factory interface,
   *  workers will be updated later 
   */
  int JK_METHOD jk_channel_socket_factory(jk_env_t *env, void **result,
  					char *type, char *name);
  
  int JK_METHOD jk_workerEnv_factory(jk_env_t *env, void **result,
                                     char *type, char *name);
  
  int JK_METHOD jk_uriMap_factory(jk_env_t *env, void **result,
                                     char *type, char *name);
  
  
  /**
   *   Init the components that we compile in by default. 
   *   In future we should have a more flexible mechanism that would allow 
   *   different server modules to load and register various jk objects, or 
   *   even have jk load it's own modules from .so files.
   * 
   *   For now the static registrartion should work.
   */
  void JK_METHOD jk_registry_init(jk_env_t *env) {
    if( env==NULL ) {
      /* XXX do something ! */
      printf("jk_registry_init: Assertion failed, env==NULL\n" );
      return;
    }
    /**
     * Because the functions being referenced here (apjp14_work_factory, and
     * lb_worker_factory) don't match the prototype declared for registerFactory,
     * and because the MetroWerks compiler (used for NetWare) treats this as an
     * error, I'm casting the function pointers to (void *) - mmanders
     */
    env->registerFactory( env, "workerEnv", "default", &jk_workerEnv_factory );
    env->registerFactory( env, "uriMap", "default",    &jk_uriMap_factory );
    env->registerFactory( env, "worker", "ajp13", &jk_worker_ajp14_factory );
    env->registerFactory( env, "worker", "ajp14", &jk_worker_ajp14_factory );
    env->registerFactory( env, "worker", "lb",    &jk_worker_lb_factory );
    env->registerFactory( env, "channel", "socket", &jk_channel_socket_factory );
  
    /* Optional objects */
  
  #ifdef HAVE_JNI
    env->registerFactory( env, "worker", "jni",   &jk_worker_jni_factory );
  #endif
  #ifdef AJP12
    env->registerFactory( env, "worker", "ajp12", &jk_worker_ajp12_factory );
  #endif
  
  
  }
  
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/native2/common/jk_util.c
  
  Index: jk_util.c
  ===================================================================
  /* ========================================================================= *
   *                                                                           *
   *                 The Apache Software License,  Version 1.1                 *
   *                                                                           *
   *          Copyright (c) 1999-2001 The Apache Software Foundation.          *
   *                           All rights reserved.                            *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * Redistribution and use in source and binary forms,  with or without modi- *
   * fication, are permitted provided that the following conditions are met:   *
   *                                                                           *
   * 1. Redistributions of source code  must retain the above copyright notice *
   *    notice, this list of conditions and the following disclaimer.          *
   *                                                                           *
   * 2. Redistributions  in binary  form  must  reproduce the  above copyright *
   *    notice,  this list of conditions  and the following  disclaimer in the *
   *    documentation and/or other materials provided with the distribution.   *
   *                                                                           *
   * 3. The end-user documentation  included with the redistribution,  if any, *
   *    must include the following acknowlegement:                             *
   *                                                                           *
   *       "This product includes  software developed  by the Apache  Software *
   *        Foundation <http://www.apache.org/>."                              *
   *                                                                           *
   *    Alternately, this acknowlegement may appear in the software itself, if *
   *    and wherever such third-party acknowlegements normally appear.         *
   *                                                                           *
   * 4. The names  "The  Jakarta  Project",  "Jk",  and  "Apache  Software     *
   *    Foundation"  must not be used  to endorse or promote  products derived *
   *    from this  software without  prior  written  permission.  For  written *
   *    permission, please contact <apache@apache.org>.                        *
   *                                                                           *
   * 5. Products derived from this software may not be called "Apache" nor may *
   *    "Apache" appear in their names without prior written permission of the *
   *    Apache Software Foundation.                                            *
   *                                                                           *
   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
   * INCLUDING, BUT NOT LIMITED TO,  THE IMPLIED WARRANTIES OF MERCHANTABILITY *
   * AND FITNESS FOR  A PARTICULAR PURPOSE  ARE DISCLAIMED.  IN NO EVENT SHALL *
   * THE APACHE  SOFTWARE  FOUNDATION OR  ITS CONTRIBUTORS  BE LIABLE  FOR ANY *
   * DIRECT,  INDIRECT,   INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL *
   * DAMAGES (INCLUDING,  BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE GOODS *
   * OR SERVICES;  LOSS OF USE,  DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION) *
   * HOWEVER CAUSED AND  ON ANY  THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT, *
   * STRICT LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
   * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF  ADVISED  OF THE *
   * POSSIBILITY OF SUCH DAMAGE.                                               *
   *                                                                           *
   * ========================================================================= *
   *                                                                           *
   * This software  consists of voluntary  contributions made  by many indivi- *
   * duals on behalf of the  Apache Software Foundation.  For more information *
   * on the Apache Software Foundation, please see <http://www.apache.org/>.   *
   *                                                                           *
   * ========================================================================= */
  
  /***************************************************************************
   * Description: Utility functions (mainly configuration)                   *
   * Author:      Gal Shachor <shachor@il.ibm.com>                           *
   * Author:      Henri Gomez <hgomez@slib.fr>                               *
   * Version:     $Revision: 1.1 $                                           *
   ***************************************************************************/
  
  
  #include "jk_util.h"
  
  #define SYSPROPS_OF_WORKER          ("sysprops")
  #define STDERR_OF_WORKER            ("stderr")
  #define STDOUT_OF_WORKER            ("stdout")
  #define MX_OF_WORKER                ("mx")
  #define MS_OF_WORKER                ("ms")
  #define CP_OF_WORKER                ("class_path")
  #define JVM_OF_WORKER               ("jvm_lib")
  #define LIBPATH_OF_WORKER           ("ld_path")
  #define CMD_LINE_OF_WORKER          ("cmd_line")
  #define NATIVE_LIB_OF_WORKER        ("native_lib")
  #define PREFIX_OF_WORKER            ("worker")
  #define HOST_OF_WORKER              ("host")
  #define PORT_OF_WORKER              ("port")
  #define TYPE_OF_WORKER              ("type")
  #define CACHE_OF_WORKER             ("cachesize")
  #define LOAD_FACTOR_OF_WORKER       ("lbfactor")
  #define BALANCED_WORKERS            ("balanced_workers")
  #define WORKER_AJP12                ("ajp12")
  #define DEFAULT_WORKER_TYPE         ("ajp13")
  #define SECRET_KEY_OF_WORKER        ("secretkey")
  
  #define DEFAULT_WORKER              ("ajp13")
  #define WORKER_LIST_PROPERTY_NAME   ("worker.list")
  #define DEFAULT_LB_FACTOR           (1.0)
  
  
  /* [V] I suggest that the following general purpose functions be used.       */
  /*     More should be added (double etc.), but now these were enough for me. */
  /*     Functions that can be simulated with these should be "deprecated".    */
  
  int jk_get_worker_str_prop(jk_map_t *m,
  			   const char *wname,
  			   const char *pname,
  			   char **prop)
  {
      char buf[1024];
  
      if(m && prop && wname && pname) {
          sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname, pname);
          *prop = map_get_string(m, buf, NULL);
          if(*prop) {
              return JK_TRUE;
          }
      }
      return JK_FALSE;
  }
  
  int jk_get_worker_int_prop(jk_map_t *m,
  			   const char *wname,
  			   const char *pname,
  			   int *prop)
  {
      char buf[1024];
  
      if(m && prop && wname && pname) {
          int i;
          sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname, pname);
          i = map_get_int(m, buf, -1);
          if(-1 != i) {
              *prop = i;
              return JK_TRUE;
          }
      }
      return JK_FALSE;
  }
  
  char *jk_get_worker_host(jk_map_t *m,
                           const char *wname,
                           const char *def)
  {
      char buf[1024];
  
      if(!m || !wname) {
          return NULL;
      }
  
      sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname, HOST_OF_WORKER);
  
      return map_get_string(m, buf, def);
  }
  
  int jk_get_worker_port(jk_map_t *m,
                         const char *wname,
                         int def)
  {
      char buf[1024];
  
      if(!m || !wname) {
          return -1;
      }
  
      sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname, PORT_OF_WORKER);
  
      return map_get_int(m, buf, def);
  }
  
  int jk_get_worker_cache_size(jk_map_t *m, 
                               const char *wname,
                               int def)
  {
      char buf[1024];
  
      if(!m || !wname) {
          return -1;
      }
  
      sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname, CACHE_OF_WORKER);
  
      return map_get_int(m, buf, def);
  }
  
  char * jk_get_worker_secret_key(jk_map_t *m,
                                  const char *wname)
  {
      char buf[1024];
  
      if(!m || !wname) {
          return NULL;
      }
  
      sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname, SECRET_KEY_OF_WORKER);
  	return map_get_string(m, buf, NULL);
  }
  
  int jk_get_worker_list(jk_map_t *m,
                         char ***list,
                         unsigned *num_of_wokers)
  {
      if(m && list && num_of_wokers) {
          char **ar = map_get_string_list(m, 
                                          WORKER_LIST_PROPERTY_NAME, 
                                          num_of_wokers, 
                                          DEFAULT_WORKER);
          if(ar)  {
              *list = ar;     
              return JK_TRUE;
          }
          *list = NULL;   
          *num_of_wokers = 0;
      }
  
      return JK_FALSE;
  }
  
  double jk_get_lb_factor(jk_map_t *m, 
                          const char *wname)
  {
      char buf[1024];
      
      if(!m || !wname) {
          return DEFAULT_LB_FACTOR;
      }
  
      sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname, LOAD_FACTOR_OF_WORKER);
  
      return map_get_double(m, buf, DEFAULT_LB_FACTOR);
  }
  
  int jk_get_lb_worker_list(jk_map_t *m, 
                            const char *lb_wname,
                            char ***list, 
                            unsigned *num_of_wokers)
  {
      char buf[1024];
  
      if(m && list && num_of_wokers && lb_wname) {
          char **ar = NULL;
  
          sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, lb_wname, BALANCED_WORKERS);
          ar = map_get_string_list(m, buf, num_of_wokers, NULL);
          if(ar)  {
              *list = ar;     
              return JK_TRUE;
          }
          *list = NULL;   
          *num_of_wokers = 0;
      }
  
      return JK_FALSE;
  }
  
  int jk_get_worker_mx(jk_map_t *m, 
                       const char *wname,
                       unsigned *mx)
  {
      char buf[1024];
      
      if(m && mx && wname) {
          int i;
          sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname, MX_OF_WORKER);
  
          i = map_get_int(m, buf, -1);
          if(-1 != i) {
              *mx = (unsigned)i;
              return JK_TRUE;
          }
      }
  
      return JK_FALSE;
  }
  
  int jk_get_worker_ms(jk_map_t *m, 
                       const char *wname,
                       unsigned *ms)
  {
      char buf[1024];
      
      if(m && ms && wname) {
          int i;
          sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname, MS_OF_WORKER);
  
          i = map_get_int(m, buf, -1);
          if(-1 != i) {
              *ms = (unsigned)i;
              return JK_TRUE;
          }
      }
  
      return JK_FALSE;
  }
  
  int jk_get_worker_classpath(jk_map_t *m, 
                              const char *wname, 
                              char **cp)
  {
      char buf[1024];
      
      if(m && cp && wname) {
          sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname, CP_OF_WORKER);
  
          *cp = map_get_string(m, buf, NULL);
          if(*cp) {
              return JK_TRUE;
          }
      }
  
      return JK_FALSE;
  }
  
  int jk_get_worker_jvm_path(jk_map_t *m, 
                             const char *wname, 
                             char **vm_path)
  {
      char buf[1024];
      
      if(m && vm_path && wname) {
          sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname, JVM_OF_WORKER);
  
          *vm_path = map_get_string(m, buf, NULL);
          if(*vm_path) {
              return JK_TRUE;
          }
      }
  
      return JK_FALSE;
  }
  
  /* [V] This is unused. currently. */
  int jk_get_worker_callback_dll(jk_map_t *m, 
                                 const char *wname, 
                                 char **cb_path)
  {
      char buf[1024];
  
      if(m && cb_path && wname) {
          sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname, NATIVE_LIB_OF_WORKER);
  
          *cb_path = map_get_string(m, buf, NULL);
          if(*cb_path) {
              return JK_TRUE;
          }
      }
  
      return JK_FALSE;
  }
  
  int jk_get_worker_cmd_line(jk_map_t *m, 
                             const char *wname, 
                             char **cmd_line)
  {
      char buf[1024];
  
      if(m && cmd_line && wname) {
          sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname, CMD_LINE_OF_WORKER);
  
          *cmd_line = map_get_string(m, buf, NULL);
          if(*cmd_line) {
              return JK_TRUE;
          }
      }
  
      return JK_FALSE;
  }
  
  static int jk_is_some_property(const char *prp_name, const char *suffix)
  {
      if (prp_name && suffix) {
  		size_t prp_name_len = strlen(prp_name);
  		size_t suffix_len = strlen(suffix);
  		if (prp_name_len >= suffix_len) {
  			const char *prp_suffix = prp_name + prp_name_len - suffix_len;
  			if(0 == strcmp(suffix, prp_suffix)) {
  		        return JK_TRUE;
  			}
          }
      }
  
      return JK_FALSE;
  }
  
  int jk_is_path_poperty(const char *prp_name)
  {
  	return jk_is_some_property(prp_name, "path");
  }
  
  int jk_is_cmd_line_poperty(const char *prp_name)
  {
  	return jk_is_some_property(prp_name, CMD_LINE_OF_WORKER);
  }
  
  int jk_get_worker_stdout(jk_map_t *m, 
                           const char *wname, 
                           char **stdout_name)
  
  {
      char buf[1024];
  
      if(m && stdout_name && wname) {
          sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname, STDOUT_OF_WORKER);
  
          *stdout_name = map_get_string(m, buf, NULL);
          if(*stdout_name) {
              return JK_TRUE;
          }
      }
  
      return JK_FALSE;
  }
  
  int jk_get_worker_stderr(jk_map_t *m, 
                           const char *wname, 
                           char **stderr_name)
  
  {
      char buf[1024];
  
      if(m && stderr_name && wname) {
          sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname, STDERR_OF_WORKER);
  
          *stderr_name = map_get_string(m, buf, NULL);
          if(*stderr_name) {
              return JK_TRUE;
          }
      }
  
      return JK_FALSE;
  }
  
  int jk_get_worker_sysprops(jk_map_t *m, 
                             const char *wname, 
                             char **sysprops)
  
  {
      char buf[1024];
  
      if(m && sysprops && wname) {
          sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname, SYSPROPS_OF_WORKER);
  
          *sysprops = map_get_string(m, buf, NULL);
          if(*sysprops) {
              return JK_TRUE;
          }
      }
  
      return JK_FALSE;
  }
  
  int jk_get_worker_libpath(jk_map_t *m, 
                            const char *wname, 
                            char **libpath)
  {
      char buf[1024];
  
      if(m && libpath && wname) {
          sprintf(buf, "%s.%s.%s", PREFIX_OF_WORKER, wname, LIBPATH_OF_WORKER);
  
          *libpath = map_get_string(m, buf, NULL);
          if(*libpath) {
              return JK_TRUE;
          }
      }
  
      return JK_FALSE;
  }
  
  char **jk_parse_sysprops(jk_pool_t *p, 
                           const char *sysprops)
  {
      char **rc = NULL;
  
      if(p && sysprops) {
          char *prps = jk_pool_strdup(p, sysprops);
          if(prps && strlen(prps)) {
              unsigned num_of_prps;
  
              for(num_of_prps = 1; *sysprops ; sysprops++) {
                  if('*' == *sysprops) {
                      num_of_prps++;
                  }
              }            
  
              rc = jk_pool_alloc(p, (num_of_prps + 1) * sizeof(char *));
              if(rc) {
                  unsigned i = 0;
                  char *tmp = strtok(prps, "*");
  
                  while(tmp && i < num_of_prps) {
                      rc[i] = tmp;
                      tmp = strtok(NULL, "*");
                      i++;
                  }
                  rc[i] = NULL;
              }
          }
      }
  
      return rc;
  }
  
  void jk_append_libpath(jk_pool_t *p, 
                         const char *libpath)
  {
      char *env = NULL;
      char *current = getenv(PATH_ENV_VARIABLE);
  
      if(current) {
          env = jk_pool_alloc(p, strlen(PATH_ENV_VARIABLE) + 
                                 strlen(current) + 
                                 strlen(libpath) + 5);
          if(env) {
              sprintf(env, "%s=%s%c%s", 
                      PATH_ENV_VARIABLE, 
                      libpath, 
                      PATH_SEPERATOR, 
                      current);
          }
      } else {
          env = jk_pool_alloc(p, strlen(PATH_ENV_VARIABLE) +                               
                                 strlen(libpath) + 5);
          if(env) {
              sprintf(env, "%s=%s", PATH_ENV_VARIABLE, libpath);
          }
      }
  
      if(env) {
          putenv(env);
      }
  }
  
  void jk_init_ws_service(jk_ws_service_t *s)
  {
      s->ws_private           = NULL;
      s->pool                 = NULL;
      s->method               = NULL;
      s->protocol             = NULL;
      s->req_uri              = NULL;
      s->remote_addr          = NULL;
      s->remote_host          = NULL;
      s->remote_user          = NULL;
      s->auth_type            = NULL;
      s->query_string         = NULL;
      s->server_name          = NULL;
      s->server_port          = 80;
      s->server_software      = NULL;
      s->content_length       = 0;
      s->is_chunked           = 0;
      s->no_more_chunks       = 0;
      s->content_read         = 0;
      s->is_ssl               = JK_FALSE;
      s->ssl_cert             = NULL;
      s->ssl_cert_len         = 0;
      s->ssl_cipher           = NULL;
      s->ssl_session          = NULL;
      s->headers_names        = NULL;
      s->headers_values       = NULL;
      s->num_headers          = 0;
      s->attributes_names     = NULL;
      s->attributes_values    = NULL;
      s->num_attributes       = 0;
      s->jvm_route            = NULL;
  }
  
  
  

--
To unsubscribe, e-mail:   <mailto:tomcat-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:tomcat-dev-help@jakarta.apache.org>


Mime
View raw message