trafficserver-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From iga...@apache.org
Subject svn commit: r1059969 [4/6] - in /trafficserver/traffic/trunk: ./ ci/ proxy/config/ proxy/mgmt/ proxy/mgmt/api/ proxy/mgmt/api/include/ proxy/mgmt/api/remote/ proxy/mgmt/cli/ proxy/mgmt/cli2/ proxy/mgmt/cluster/ proxy/mgmt/html2/ proxy/mgmt/html2/charti...
Date Mon, 17 Jan 2011 16:11:34 GMT
Copied: trafficserver/traffic/trunk/proxy/mgmt/web2/WebConfigRender.h (from r1059438, trafficserver/traffic/trunk/proxy/mgmt/web2/WebConfigRender.h)
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/mgmt/web2/WebConfigRender.h?p2=trafficserver/traffic/trunk/proxy/mgmt/web2/WebConfigRender.h&p1=trafficserver/traffic/trunk/proxy/mgmt/web2/WebConfigRender.h&r1=1059438&r2=1059969&rev=1059969&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/mgmt/web2/WebConfigRender.h (original)
+++ trafficserver/traffic/trunk/proxy/mgmt/web2/WebConfigRender.h Mon Jan 17 16:11:27 2011
@@ -33,37 +33,120 @@
 #define _WEB_CONFIG_RENDER_H_
 
 #include "TextBuffer.h"
+#include "WebHttpContext.h"
 
 #include "P_RecCore.h"
 
+int writeCacheConfigTable(WebHttpContext * whc);
 int writeCacheRuleList(textBuffer * output);
+int writeCacheConfigForm(WebHttpContext * whc);
 
+int writeHostingConfigTable(WebHttpContext * whc);
 int writeHostingRuleList(textBuffer * output);
+int writeHostingConfigForm(WebHttpContext * whc);
 
+int writeIcpConfigTable(WebHttpContext * whc);
 int writeIcpRuleList(textBuffer * output);
+int writeIcpConfigForm(WebHttpContext * whc);
 
+int writeIpAllowConfigTable(WebHttpContext * whc);
 int writeIpAllowRuleList(textBuffer * output);
+int writeIpAllowConfigForm(WebHttpContext * whc);
 
+int writeMgmtAllowConfigTable(WebHttpContext * whc);
+int writeMgmtAllowRuleList(textBuffer * output);
+int writeMgmtAllowConfigForm(WebHttpContext * whc);
+
+int writeParentConfigTable(WebHttpContext * whc);
 int writeParentRuleList(textBuffer * output);
+int writeParentConfigForm(WebHttpContext * whc);
 
+int writePartitionConfigTable(WebHttpContext * whc);
 int writePartitionRuleList(textBuffer * output);
+int writePartitionConfigForm(WebHttpContext * whc);
 
+int writeRemapConfigTable(WebHttpContext * whc);
 int writeRemapRuleList(textBuffer * output);
+int writeRemapConfigForm(WebHttpContext * whc);
 
+int writeSocksConfigTable(WebHttpContext * whc);
 int writeSocksRuleList(textBuffer * output);
+int writeSocksConfigForm(WebHttpContext * whc);
 
+int writeSplitDnsConfigTable(WebHttpContext * whc);
 int writeSplitDnsRuleList(textBuffer * output);
+int writeSplitDnsConfigForm(WebHttpContext * whc);
 
+int writeUpdateConfigTable(WebHttpContext * whc);
 int writeUpdateRuleList(textBuffer * output);
+int writeUpdateConfigForm(WebHttpContext * whc);
 
+int writeVaddrsConfigTable(WebHttpContext * whc);
 int writeVaddrsRuleList(textBuffer * output);
+int writeVaddrsConfigForm(WebHttpContext * whc);
 
+int writeSecondarySpecsForm(WebHttpContext * whc, INKFileNameT file);
 int writeSecondarySpecsTableElem(textBuffer * output, char *time, char *src_ip, char *prefix, char *suffix, char *port,
                                  char *method, char *scheme, char *mixt);
 
 
 // -------------------- CONVERSION FUNCTIONS ------------------------------
 
+int convert_cache_ele_to_html_format(INKCacheEle * ele,
+                                     char *ruleType,
+                                     char *pdType,
+                                     char *time,
+                                     char *src_ip,
+                                     char *prefix,
+                                     char *suffix,
+                                     char *port, char *method, char *scheme, char *time_period, char *mixt);
+
+int convert_hosting_ele_to_html_format(INKHostingEle * ele, char *pdType, char *partitions);
+
+int convert_icp_ele_to_html_format(INKIcpEle * ele,
+                                   char *name,
+                                   char *host_ip,
+                                   char *peer_type,
+                                   char *proxy_port, char *icp_port, char *mc_state, char *mc_ip, char *mc_ttl);
+
+int convert_ip_allow_ele_to_html_format(INKIpAllowEle * ele, char *src_ip, char *action);
+
+int convert_mgmt_allow_ele_to_html_format(INKMgmtAllowEle * ele, char *src_ip, char *action);
+
+int convert_parent_ele_to_html_format(INKParentProxyEle * ele,
+                                      char *pdType,
+                                      char *time,
+                                      char *src_ip,
+                                      char *prefix,
+                                      char *suffix,
+                                      char *port,
+                                      char *method,
+                                      char *scheme, char *mixt, char *parents, char *round_robin, char *direct);
+
+int convert_partition_ele_to_html_format(INKPartitionEle * ele,
+                                         char *part_num, char *scheme, char *size, char *size_fmt);
+
+int convert_remap_ele_to_html_format(INKRemapEle * ele,
+                                     char *rule_type,
+                                     char *from_scheme, char *from_port, char *from_path,
+                                     char *to_scheme, char *to_port, char *to_path, char *mixt);
+
+int convert_socks_ele_to_html_format(INKSocksEle * ele,
+                                     char *rule_type, char *dest_ip, char *user, char *passwd, char *servers, char *rr);
+
+int convert_split_dns_ele_to_html_format(INKSplitDnsEle * ele,
+                                         char *pdType, char *dns_server, char *def_domain, char *search_list);
+
+int convert_update_ele_to_html_format(INKUpdateEle * ele, char *hdrs, char *offset, char *interval, char *depth);
+
+int convert_virt_ip_addr_ele_to_html_format(INKVirtIpAddrEle * ele, char *ip, char *sub_intr);
+
+int convert_pdss_to_html_format(INKPdSsFormat info,
+                                char *pdType,
+                                char *time,
+                                char *src_ip,
+                                char *prefix, char *suffix, char *port, char *method, char *scheme, char *mixt);
+
 //------------------------- SELECT FUNCTIONS ------------------------------
 
 void writeRuleTypeSelect_cache(textBuffer * html, const char *listName);

Modified: trafficserver/traffic/trunk/proxy/mgmt/web2/WebGlobals.h
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/mgmt/web2/WebGlobals.h?rev=1059969&r1=1059968&r2=1059969&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/mgmt/web2/WebGlobals.h (original)
+++ trafficserver/traffic/trunk/proxy/mgmt/web2/WebGlobals.h Mon Jan 17 16:11:27 2011
@@ -45,6 +45,7 @@
 
 #include "ink_mutex.h"
 #include "MgmtHashTable.h"
+#include "WebHttpAuth.h"
 
 extern "C"
 {
@@ -91,6 +92,22 @@ struct serviceThr_t
 //  since prior transactions in the system will STILL
 //  BE USING the memory pointed to.
 //
+struct WebContext
+{
+  const char *defaultFile;
+  char *docRoot;
+  int docRootLen;
+  char *pluginDocRoot;
+  int pluginDocRootLen;
+  int adminAuthEnabled;
+  WebHttpAuthUser admin_user;   // admin user (always available)
+  MgmtHashTable *other_users_ht;        // other users (can change dynamically)
+  MgmtHashTable *lang_dict_ht;  // language dictionary (tag to string)
+  int SSLenabled;
+  int AdvUIEnabled;             /* 0=Simple UI, 1=Full UI, 2=RNI UI */
+  int FeatureSet;               /* bit field of features */
+  ssl_ctx_st *SSL_Context;
+};
 
 struct WebInterFaceGlobals
 {
@@ -111,6 +128,8 @@ struct WebInterFaceGlobals
 };
 
 extern WebInterFaceGlobals wGlobals;
+extern WebContext adminContext;
+extern WebContext autoconfContext;
 
 #define MAX_SERVICE_THREADS 100
 #define MAX_VAR_LENGTH      256
@@ -146,5 +165,11 @@ extern WebInterFaceGlobals wGlobals;
 #define WEB_MAX_PAGE_QUERY_LEN             (32+1)
 #define WEB_MAX_EDIT_FILE_SIZE             (32*1024)    // Some browsers limit you to this
 
+struct WebHttpConInfo
+{
+  int fd;
+  WebContext *context;
+  sockaddr_in *clientInfo;
+};
 
 #endif

Copied: trafficserver/traffic/trunk/proxy/mgmt/web2/WebHttp.cc (from r1059429, trafficserver/traffic/trunk/proxy/mgmt/web2/WebHttp.cc)
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/mgmt/web2/WebHttp.cc?p2=trafficserver/traffic/trunk/proxy/mgmt/web2/WebHttp.cc&p1=trafficserver/traffic/trunk/proxy/mgmt/web2/WebHttp.cc&r1=1059429&r2=1059969&rev=1059969&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/mgmt/web2/WebHttp.cc (original)
+++ trafficserver/traffic/trunk/proxy/mgmt/web2/WebHttp.cc Mon Jan 17 16:11:27 2011
@@ -39,8 +39,10 @@
 #include "WebHttp.h"
 #include "WebHttpAuth.h"
 #include "WebHttpContext.h"
+#include "WebHttpLog.h"
 #include "WebHttpMessage.h"
 #include "WebHttpRender.h"
+#include "WebHttpSession.h"
 #include "WebHttpTree.h"
 #include "WebOverview.h"
 #include "WebConfig.h"
@@ -109,6 +111,30 @@ InkHashTable *g_display_config_ht = 0;
 
 void spawn_script(WebHttpContext * whc, char *script, char **args);
 
+//-------------------------------------------------------------------------
+// record_version_valid
+//-------------------------------------------------------------------------
+
+static bool
+record_version_valid(char *record_version)
+{
+  int old_version, old_pid, cur_version;
+  // coverity[secure_coding]
+  if (sscanf(record_version, "%d:%d", &old_pid, &old_version) == 2 && old_version >= 0) {
+    cur_version = RecGetRecordUpdateCount(RECT_CONFIG);
+    //fix me --> lmgmt->record_data->pid
+    // TODO: need to check the PID ??
+    //    if (cur_version != old_version || lmgmt->record_data->pid != old_pid) {
+    if (cur_version != old_version) {
+      // we are out of date since the version number has been incremented
+      return false;
+    } else {
+      return true;
+    }
+  }
+  // bad format, return false to be safe
+  return false;
+}
 
 //-------------------------------------------------------------------------
 // set_record_value
@@ -135,8 +161,8 @@ set_record_value(WebHttpContext * whc, c
     script++;
   }
   // FIXME: If someone else has already added a NOTE or WARN, then we
-  // won't be able to add anymore.  This was desired for
-  // handle_submit_update(), but going forward, we'll need a more
+  // won't be able to add anymore.  This is desired for
+  // handle_submit_update, but going forward, we'll need a more
   // general mechanism.
 
   varValue.setFromName(record);
@@ -177,6 +203,56 @@ set_record_value(WebHttpContext * whc, c
   return true;
 }
 
+//-------------------------------------------------------------------------
+// set_config_file
+//-------------------------------------------------------------------------
+
+static bool
+set_config_file(WebHttpContext * whc, char *file_version, char *file_contents, char *file_checksum)
+{
+
+  bool err = true;
+
+  Rollback *rb;
+  textBuffer *tb;
+  version_t fversion;
+  char frecord[MAX_VAR_LENGTH + 1];
+  char fname[MAX_VAL_LENGTH + 1];
+  char checksum[MAX_CHECKSUM_LENGTH + 1];
+  int file_size;
+
+  // coverity[secure_coding]
+  if (sscanf(file_version, "%d:%s", &fversion, frecord) == 2) {
+    if (varStrFromName(frecord, fname, MAX_VAL_LENGTH)) {
+      if (configFiles->getRollbackObj(fname, &rb)) {
+        // INKqa12198: remove ^M (CR) from each line in file_contents
+        convertHtmlToUnix(file_contents);
+        file_size = strlen(file_contents);
+        tb = NEW(new textBuffer(file_size + 1));
+        tb->copyFrom(file_contents, file_size); //orig
+
+        // calculate checksum - skip file update if match checksum
+        fileCheckSum(tb->bufPtr(), tb->spaceUsed(), checksum, sizeof(checksum));
+        if (strcmp(file_checksum, checksum) != 0) {
+          if (rb->updateVersion(tb, fversion) != OK_ROLLBACK) {
+            err = false;
+          }
+          // put note if file update required restart
+          if (recordRestartCheck(frecord)) {
+            ink_hash_table_insert(whc->submit_note_ht, frecord, NULL);
+            if (!(whc->request_state & WEB_HTTP_STATE_SUBMIT_NOTE)) {
+              HtmlRndrText(whc->submit_note, whc->lang_dict_ht, HTML_ID_RESTART_REQUIRED);
+              HtmlRndrBr(whc->submit_note);
+            }
+            whc->request_state |= WEB_HTTP_STATE_SUBMIT_NOTE;
+          }
+        }
+        delete tb;
+      }
+    }
+  }
+  return err;
+}
 
 //-------------------------------------------------------------------------
 // spawn_cgi
@@ -648,6 +724,20 @@ Ldone:
 #undef BUF_SIZE
 #undef NULL_STR
 
+static int
+handle_config_files(WebHttpContext * whc, const char *file)
+{
+  NOWARN_UNUSED(file);
+  return WebHttpRender(whc, HTML_FILE_ALL_CONFIG);
+}
+
+static int
+handle_debug_logs(WebHttpContext * whc, const char *file)
+{
+  NOWARN_UNUSED(file);
+  return WebHttpRender(whc, HTML_VIEW_DEBUG_LOGS_FILE);
+}
+
 //-------------------------------------------------------------------------
 // handle_synthetic
 //-------------------------------------------------------------------------
@@ -685,6 +775,10 @@ handle_submit_alarm(WebHttpContext * whc
   return handle_ink_extn(whc, HTML_ALARM_FILE);
 }
 
+//-------------------------------------------------------------------------
+// handle_submit_mgmt_auth
+//-------------------------------------------------------------------------
+
 // set_admin_passwd (sub-function)
 static inline void
 set_admin_passwd(WebHttpContext * whc)
@@ -757,6 +851,665 @@ set_admin_passwd(WebHttpContext * whc)
 
 }
 
+static int
+handle_submit_mgmt_auth(WebHttpContext * whc, const char *file)
+{
+  NOWARN_UNUSED(file);
+  bool recs_out_of_date;
+  char *value;
+  char *cancel;
+  char *record_version;
+  char *submit_from_page;
+  char *aa_session_id, *aa_user_count;
+  char *aa_user, *aa_access, *aa_delete;
+  char *aa_new_user, *aa_new_passwd, *aa_new_passwd_retype, *aa_new_access;
+  char *aa_new_epasswd;
+  char admin_user[MAX_VAL_LENGTH + 1];
+  int user, user_count;
+  INKCfgContext ctx;
+  INKAdminAccessEle *ele;
+  INKActionNeedT action_need;
+  INKAccessT access_t;
+  bool ctx_updated;
+
+  char tmp_a[32];
+  char tmp_b[32];
+
+  char empty_str[1];
+  *empty_str = '\0';
+
+  // initialize pointers we may assign memeory to
+  aa_new_epasswd = NULL;
+
+  // check for submit_from_page
+  if (ink_hash_table_lookup(whc->post_data_ht, "submit_from_page", (void **) &submit_from_page)) {
+    ink_hash_table_delete(whc->post_data_ht, "submit_from_page");
+    whc->top_level_render_file = xstrdup(submit_from_page);
+  } else {
+    submit_from_page = NULL;
+  }
+
+  // check for cancel
+  if (ink_hash_table_lookup(whc->post_data_ht, "cancel", (void **) &cancel))
+    goto Ldone;
+
+  // check for record_version
+  recs_out_of_date = true;
+  if (ink_hash_table_lookup(whc->post_data_ht, "record_version", (void **) &record_version)) {
+    recs_out_of_date = !record_version_valid(record_version);
+    ink_hash_table_delete(whc->post_data_ht, "record_version");
+    xfree(record_version);
+  }
+  if (recs_out_of_date)
+    goto Lout_of_date;
+
+  // proxy.config.admin.basic_auth
+  if (ink_hash_table_lookup(whc->post_data_ht, "proxy.config.admin.basic_auth", (void **) &value))
+    set_record_value(whc, "proxy.config.admin.basic_auth", value);
+
+  // proxy.config.admin.admin_user
+  if (ink_hash_table_lookup(whc->post_data_ht, "proxy.config.admin.admin_user", (void **) &value))
+    set_record_value(whc, "proxy.config.admin.admin_user", value);
+
+  // proxy.config.admin.admin_password (call sub-function)
+  set_admin_passwd(whc);
+
+  // grab our session_id and user_count
+  if (ink_hash_table_lookup(whc->post_data_ht, "session_id", (void **) &aa_session_id)) {
+    if (!ink_hash_table_lookup(whc->post_data_ht, "user_count", (void **) &aa_user_count))
+      goto Lunable_to_submit;
+    // find our current session
+    if (WebHttpSessionRetrieve(aa_session_id, (void **) &ctx) != WEB_HTTP_ERR_OKAY)
+      goto Lout_of_date;
+    // get new additional-user information
+    if (!ink_hash_table_lookup(whc->post_data_ht, "new_user", (void **) &aa_new_user))
+      aa_new_user = NULL;
+    if (!ink_hash_table_lookup(whc->post_data_ht, "new_passwd", (void **) &aa_new_passwd))
+      aa_new_passwd = NULL;
+    if (!ink_hash_table_lookup(whc->post_data_ht, "new_passwd_retype", (void **) &aa_new_passwd_retype))
+      aa_new_passwd_retype = NULL;
+    if (!ink_hash_table_lookup(whc->post_data_ht, "new_access", (void **) &aa_new_access))
+      aa_new_access = NULL;
+    // check if the user is trying to add a new additional-user
+    if (aa_new_user != NULL) {
+      // kwt 12.March.2001 check for username length
+      if (strlen(aa_new_user) > WEB_HTTP_AUTH_USER_MAX) {
+        ink_hash_table_insert(whc->submit_warn_ht, "additional_administrative_accounts", NULL);
+        ink_hash_table_insert(whc->submit_warn_ht, "add_new_administrative_user", NULL);
+        whc->request_state |= WEB_HTTP_STATE_SUBMIT_WARN;
+        HtmlRndrText(whc->submit_warn, whc->lang_dict_ht, HTML_ID_NEW_USERNAME_LENGTH);
+        HtmlRndrBr(whc->submit_warn);
+        aa_new_user = NULL;
+      }
+      // kwt
+      if (aa_new_user != NULL) {
+        if (aa_new_passwd == NULL)
+          aa_new_passwd = empty_str;
+        if (aa_new_passwd_retype == NULL)
+          aa_new_passwd_retype = empty_str;
+        if (strcmp(aa_new_passwd, aa_new_passwd_retype) == 0) {
+          // allocating memory on aa_new_epasswd
+          INKEncryptPassword(aa_new_passwd, &aa_new_epasswd);
+        } else {
+          ink_hash_table_insert(whc->submit_warn_ht, "additional_administrative_accounts", NULL);
+          ink_hash_table_insert(whc->submit_warn_ht, "add_new_administrative_user", NULL);
+          whc->request_state |= WEB_HTTP_STATE_SUBMIT_WARN;
+          HtmlRndrText(whc->submit_warn, whc->lang_dict_ht, HTML_ID_NEW_PASSWD_MISTYPE);
+          HtmlRndrBr(whc->submit_warn);
+        }
+      }
+      // check if the new_user is the same as the proxy.config.admin.admin_user
+      if (aa_new_user != NULL) {
+        varStrFromName("proxy.config.admin.admin_user", admin_user, MAX_VAL_LENGTH + 1);
+        if (strcmp(aa_new_user, admin_user) == 0) {
+          ink_hash_table_insert(whc->submit_warn_ht, "additional_administrative_accounts", NULL);
+          ink_hash_table_insert(whc->submit_warn_ht, "add_new_administrative_user", NULL);
+          whc->request_state |= WEB_HTTP_STATE_SUBMIT_WARN;
+          HtmlRndrText(whc->submit_warn, whc->lang_dict_ht, HTML_ID_NEW_USER_DUPLICATE);
+          HtmlRndrBr(whc->submit_warn);
+          aa_new_user = NULL;
+        }
+      }
+    }
+    // Walk through members and update settings in ctx backwards.
+    // Client submitted values should be in the same order as the ctx
+    // since we originally created this page from the same ctx.
+    // Looping backwards helps so that we can delete elements by
+    // index.
+    ctx_updated = false;
+    user_count = ink_atoi(aa_user_count);
+    for (user = user_count - 1; user >= 0; user--) {
+      snprintf(tmp_a, sizeof(tmp_a), "user:%d", user);
+      snprintf(tmp_b, sizeof(tmp_b), "access:%d", user);
+      if (ink_hash_table_lookup(whc->post_data_ht, tmp_a, (void **) &aa_user) &&
+          ink_hash_table_lookup(whc->post_data_ht, tmp_b, (void **) &aa_access)) {
+        snprintf(tmp_a, sizeof(tmp_a), "delete:%d", user);
+        if (ink_hash_table_lookup(whc->post_data_ht, tmp_a, (void **) &aa_delete)) {
+          INKCfgContextRemoveEleAt(ctx, user);
+          ctx_updated = true;
+          continue;
+        }
+        ele = (INKAdminAccessEle *) INKCfgContextGetEleAt(ctx, user);
+        if (strcmp(ele->user, aa_user) != 0) {
+          goto Lunable_to_submit;
+        }
+        if (aa_new_user && (strcmp(aa_new_user, aa_user) == 0)) {
+          ink_hash_table_insert(whc->submit_warn_ht, "additional_administrative_accounts", NULL);
+          ink_hash_table_insert(whc->submit_warn_ht, "add_new_administrative_user", NULL);
+          whc->request_state |= WEB_HTTP_STATE_SUBMIT_WARN;
+          HtmlRndrText(whc->submit_warn, whc->lang_dict_ht, HTML_ID_NEW_USER_DUPLICATE);
+          HtmlRndrBr(whc->submit_warn);
+          aa_new_user = NULL;
+        }
+        access_t = (INKAccessT) ink_atoi(aa_access);
+        if (ele->access != access_t) {
+          ele->access = access_t;
+          ctx_updated = true;
+        }
+      } else {
+        goto Lunable_to_submit;
+      }
+    }
+    // add new user
+    if ((aa_new_user != NULL) && (aa_new_epasswd != NULL)) {
+      ele = INKAdminAccessEleCreate();
+      ele->user = xstrdup(aa_new_user);
+      ele->password = xstrdup(aa_new_epasswd);
+      // FIXME: no access for now, add back later?
+      //ele->access = aa_new_access ? (INKAccessT)ink_atoi(aa_new_access) : INK_ACCESS_NONE;
+      ele->access = INK_ACCESS_NONE;
+      INKCfgContextAppendEle(ctx, (INKCfgEle *) ele);
+      ctx_updated = true;
+    }
+    if (ctx_updated) {
+      if (INKCfgContextCommit(ctx, &action_need, NULL) != INK_ERR_OKAY) {
+        WebHttpSessionDelete(aa_session_id);
+        goto Lout_of_date;
+      }
+      INKActionDo(action_need);
+    }
+    WebHttpSessionDelete(aa_session_id);
+  } else {
+    goto Lunable_to_submit;
+  }
+  goto Ldone;
+
+Lout_of_date:
+  whc->request_state |= WEB_HTTP_STATE_SUBMIT_WARN;
+  HtmlRndrText(whc->submit_warn, whc->lang_dict_ht, HTML_ID_OUT_OF_DATE);
+  HtmlRndrBr(whc->submit_warn);
+  goto Ldone;
+
+Lunable_to_submit:
+  whc->request_state |= WEB_HTTP_STATE_SUBMIT_WARN;
+  HtmlRndrText(whc->submit_warn, whc->lang_dict_ht, HTML_ID_UNABLE_TO_SUBMIT);
+  HtmlRndrBr(whc->submit_warn);
+  goto Ldone;
+
+Ldone:
+  if (aa_new_epasswd) {
+    xfree(aa_new_epasswd);
+  }
+  return WebHttpRender(whc, HTML_MGMT_LOGIN_FILE);
+}
+
+
+
+
+
+
+
+//-------------------------------------------------------------------------
+// handle_submit_snapshot_to_filesystem
+//-------------------------------------------------------------------------
+
+static int
+handle_submit_snapshot_to_filesystem(WebHttpContext * whc, const char *file)
+{
+  NOWARN_UNUSED(file);
+  int err = 0;
+  SnapResult snap_result = SNAP_OK;
+  char *submit_from_page;
+  char *snap_action;
+  char *snap_name;
+  char *snap_directory;
+  char *snapDirFromRecordsConf;
+  char *cancel;
+  bool found = false;
+  struct stat snapDirStat;
+  char config_dir[256];
+  char *record_version;
+  ExpandingArray snap_list(25, true);
+  int num_snaps;
+
+  if (varStrFromName("proxy.config.config_dir", config_dir, 256) == false)
+    mgmt_fatal(stderr,
+               "[WebHttp::handle_submit_snapshot] Unable to find configuration directory from proxy.config.config_dir\n");
+
+  // check for submit_from_page
+  if (ink_hash_table_lookup(whc->post_data_ht, "submit_from_page", (void **) &submit_from_page)) {
+    ink_hash_table_delete(whc->post_data_ht, "submit_from_page");
+    whc->top_level_render_file = xstrdup(submit_from_page);
+  } else {
+    submit_from_page = NULL;
+  }
+
+  // check for cancel
+  if (ink_hash_table_lookup(whc->post_data_ht, "cancel", (void **) &cancel)) {
+    whc->post_data_ht = NULL;
+    goto Ldone;
+  }
+  // check for record_version
+  if (ink_hash_table_lookup(whc->post_data_ht, "record_version", (void **) &record_version)) {
+    // TODO: Check return value?
+    record_version_valid(record_version);
+    ink_hash_table_delete(whc->post_data_ht, "record_version");
+    xfree(record_version);
+  }
+
+  if (ink_hash_table_lookup(whc->post_data_ht, "Change Directory", (void **) &snap_directory)) {
+    if (snap_directory == NULL) {
+      mgmt_log(stderr, "[WebHttp::handle_submit_snapshot_to_filesystem] Change Directory not specified.");
+      ink_hash_table_insert(whc->submit_warn_ht, "proxy.config.snapshot_dir", snap_directory);
+      if (!(whc->request_state & WEB_HTTP_STATE_SUBMIT_WARN)) {
+        HtmlRndrText(whc->submit_warn, whc->lang_dict_ht, HTML_ID_MISSING_ENTRY);
+        HtmlRndrBr(whc->submit_warn);
+      }
+      whc->request_state |= WEB_HTTP_STATE_SUBMIT_WARN;
+      goto Ldone;
+    } else {
+#ifndef _WIN32
+      const char *valid_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890._-/\\";
+#else
+      const char *valid_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890._-/\\ ";
+#endif
+      int snapnameLength = strlen(snap_directory);
+      int validnameLength = strspn(snap_directory, valid_chars);
+      if (snapnameLength != validnameLength) {
+        ink_hash_table_insert(whc->submit_warn_ht, "proxy.config.snapshot_dir", snap_directory);
+        if (!(whc->request_state & WEB_HTTP_STATE_SUBMIT_WARN)) {
+          HtmlRndrText(whc->submit_warn, whc->lang_dict_ht, HTML_ID_INVALID_ENTRY);
+          HtmlRndrBr(whc->submit_warn);
+        }
+        whc->request_state |= WEB_HTTP_STATE_SUBMIT_WARN;
+        goto Ldone;
+      }
+
+      RecGetRecordString_Xmalloc("proxy.config.snapshot_dir", &snapDirFromRecordsConf);
+      ink_release_assert(found);
+      if (snapDirFromRecordsConf == NULL) {
+        snapDirFromRecordsConf = new char[strlen("snapshots")];
+        snprintf(snapDirFromRecordsConf, strlen("snapshots"), "%s", "snapshots");
+        RecSetRecordString("proxy.config.snapshot_dir", snapDirFromRecordsConf);
+      }
+      if (strcasecmp(snapDirFromRecordsConf, snap_directory)) {
+        RecSetRecordString("proxy.config.snapshot_dir", snapDirFromRecordsConf);
+        // Create a directory for the snap shot
+        if (snap_directory[0] != '/') {
+          char *snap_dir_cpy = xstrdup(snap_directory);
+          int newLen;
+
+          newLen = strlen(snap_dir_cpy) + strlen(config_dir) + 2;
+          snap_directory = new char[newLen];
+          ink_assert(snap_directory != NULL);
+          snprintf(snap_directory, newLen, "%s%s%s", config_dir, DIR_SEP, snap_dir_cpy);
+          RecSetRecordString("proxy.config.snapshot_dir", snap_dir_cpy);
+          if (snap_dir_cpy)
+            free(snap_dir_cpy);
+        }
+        if (!stat(snap_directory, &snapDirStat)) {
+          bool write_possible = true;
+          bool read_possible = true;
+#ifndef _WIN32
+          if (snapDirStat.st_uid != getuid()) {
+            if (snapDirStat.st_gid != getgid()) {
+              if (!(snapDirStat.st_mode & 00002)) {
+                write_possible = false;
+              } else {
+                write_possible = true;
+              }
+            } else {
+              if (!(snapDirStat.st_mode & 00020)) {
+                write_possible = false;
+              } else {
+                write_possible = true;
+              }
+            }
+          }
+
+          if (snapDirStat.st_uid != getuid()) {
+            if (snapDirStat.st_gid != getgid()) {
+              if (!(snapDirStat.st_mode & 00004)) {
+                read_possible = false;
+              } else {
+                read_possible = true;
+              }
+            } else {
+              if (!(snapDirStat.st_mode & 00040)) {
+                read_possible = false;
+              } else {
+                read_possible = true;
+              }
+            }
+          }
+#else
+          DWORD attr;
+          attr = GetFileAttributes(snap_directory);
+          if ((attr & FILE_ATTRIBUTE_READONLY) != 0) {  // read only dir
+            write_possible = false;
+            read_possible = false;
+          } else {
+            write_possible = true;
+            read_possible = true;
+          }
+#endif // _WIN32
+          if (!write_possible) {
+            if (!read_possible) {
+              ink_hash_table_insert(whc->submit_warn_ht, "proxy.config.snapshot_dir", snap_directory);
+              if (!(whc->request_state & WEB_HTTP_STATE_SUBMIT_WARN)) {
+                HtmlRndrText(whc->submit_warn, whc->lang_dict_ht, HTML_ID_PERMISSION_DENIED);
+                HtmlRndrBr(whc->submit_warn);
+              }
+              whc->request_state |= WEB_HTTP_STATE_SUBMIT_WARN;
+              RecSetRecordString("proxy.config.snapshot_dir", snap_directory);
+              goto Ldone;
+            }
+          }
+        }
+
+        if (stat(snap_directory, &snapDirStat)) {
+          SimpleTokenizer snapDirPathTok(snap_directory, '/');
+          int dirDepth = snapDirPathTok.getNumTokensRemaining();
+
+          for (int i = 1; i <= dirDepth; i++) {
+            if (snap_directory[0] == '/') {
+              int newLen;
+              char *absoluteDir;
+              const char *tok = snapDirPathTok.getNext(i);
+
+              newLen = strlen(tok) + 2;
+              absoluteDir = new char[newLen];
+              ink_assert(absoluteDir != NULL);
+              snprintf(absoluteDir, newLen, "/%s", tok);
+
+#ifndef _WIN32
+              if (mkdir(absoluteDir, DIR_MODE) < 0) {
+#else
+              if (mkdir(absoluteDir) < 0) {
+#endif
+                perror("[WebHttp::handle_submit_snapshot_to_filesystem] Absolute snapPath Directory creation:");
+              }
+              delete[]absoluteDir;
+            } else {
+              const char *tok = snapDirPathTok.getNext(i);
+#ifndef _WIN32
+              if (mkdir(tok, DIR_MODE) < 0) {
+#else
+              if (mkdir(tok) < 0) {
+#endif
+                perror("[WebHttp::handle_submit_snapshot_to_filesystem] Relative snapPath Directory creation:");
+              }
+            }
+            snapDirPathTok.setString(snap_directory);
+          }
+        }
+      }
+    }
+  }
+
+  if (ink_hash_table_lookup(whc->post_data_ht, "SnapshotName", (void **) &snap_name)) {
+    if (snap_name != NULL) {
+#ifndef _WIN32
+      const char *valid_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890._";
+#else
+      const char *valid_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890._ ";
+#endif
+      int snapnameLength = strlen(snap_name);
+      int validnameLength = strspn(snap_name, valid_chars);
+      if (snapnameLength != validnameLength) {
+        ink_hash_table_insert(whc->submit_warn_ht, "SnapShotName", NULL);
+        if (!(whc->request_state & WEB_HTTP_STATE_SUBMIT_WARN)) {
+          HtmlRndrText(whc->submit_warn, whc->lang_dict_ht, HTML_ID_INVALID_ENTRY);
+          HtmlRndrBr(whc->submit_warn);
+        }
+        whc->request_state |= WEB_HTTP_STATE_SUBMIT_WARN;
+        goto Ldone;
+      }
+
+
+      snap_result = configFiles->WalkSnaps(&snap_list);
+      if (snap_result == SNAP_OK) {
+        num_snaps = snap_list.getNumEntries();
+        if (num_snaps > 0) {
+          for (int i = 0; i < num_snaps; i++)
+            if (!strcmp((char *) snap_list[i], snap_name)) {
+              if (ink_hash_table_lookup(whc->post_data_ht, "Delete Snapshot", (void **) &snap_action)) {
+                if (ink_hash_table_lookup(whc->post_data_ht, "restore_delete_name", (void **) &snap_action)) {
+                  if (snap_action != NULL) {
+                    if (!strcmp(snap_name, snap_action))
+                      goto Ldelete;
+                  }
+                }
+              }
+              ink_hash_table_insert(whc->submit_warn_ht, "SnapShotName", NULL);
+              if (!(whc->request_state & WEB_HTTP_STATE_SUBMIT_WARN)) {
+                HtmlRndrText(whc->submit_warn, whc->lang_dict_ht, HTML_ID_DUPLICATE_ENTRY);
+                HtmlRndrBr(whc->submit_warn);
+              }
+              whc->request_state |= WEB_HTTP_STATE_SUBMIT_WARN;
+              goto Ldone;
+            }
+        }
+        ink_hash_table_delete(whc->post_data_ht, "SnapshotName");
+      }
+
+      RecGetRecordString_Xmalloc("proxy.config.snapshot_dir", &snap_directory);
+      ink_release_assert(found);
+
+      if (snap_directory[0] != '/') {
+        char *snap_dir_cpy = xstrdup(snap_directory);
+        int newLen;
+
+        newLen = strlen(snap_dir_cpy) + strlen(config_dir) + 2;
+        snap_directory = new char[newLen];
+        ink_assert(snap_directory != NULL);
+        snprintf(snap_directory, newLen, "%s%s%s", config_dir, DIR_SEP, snap_dir_cpy);
+        if (snap_dir_cpy)
+          free(snap_dir_cpy);
+      }
+      snap_result = configFiles->takeSnap(snap_name, snap_directory);
+      if (snap_result == 3) {
+        ink_hash_table_insert(whc->submit_warn_ht, "proxy.config.snapshot_dir", snap_directory);
+        if (!(whc->request_state & WEB_HTTP_STATE_SUBMIT_WARN)) {
+          HtmlRndrText(whc->submit_warn, whc->lang_dict_ht, HTML_ID_PERMISSION_DENIED);
+          HtmlRndrBr(whc->submit_warn);
+        }
+        whc->request_state |= WEB_HTTP_STATE_SUBMIT_WARN;
+        RecSetRecordString("proxy.config.snapshot_dir", snap_directory);
+        goto Ldone;
+      }
+    }
+  }
+
+  if (ink_hash_table_lookup(whc->post_data_ht, "Restore Snapshot", (void **) &snap_action)) {
+    if (ink_hash_table_lookup(whc->post_data_ht, "restore_delete_name", (void **) &snap_name)) {
+      if (strcmp(snap_name, "- select a snapshot -")) {
+        RecGetRecordString_Xmalloc("proxy.config.snapshot_dir", &snapDirFromRecordsConf);
+        ink_release_assert(found);
+        if (snapDirFromRecordsConf[0] != '/') {
+          char *snap_dir_cpy = xstrdup(snapDirFromRecordsConf);
+          ink_assert(snap_dir_cpy);
+          int newLen;
+          newLen = strlen(snap_dir_cpy) + strlen(config_dir) + 2;
+          snapDirFromRecordsConf = new char[newLen];
+          ink_assert(snapDirFromRecordsConf != NULL);
+          snprintf(snapDirFromRecordsConf, newLen, "%s%s%s", config_dir, DIR_SEP, snap_dir_cpy);
+          if (snap_dir_cpy)
+            free(snap_dir_cpy);
+        }
+        snap_result = configFiles->restoreSnap(snap_name, snapDirFromRecordsConf);
+        if (snap_result < 0) {
+          mgmt_log(stderr, "[WebHttp::handle_submit_snapshot_to_filesystem] Restore snapshot failed");
+        }
+      }
+    }
+  }
+
+Ldelete:
+  if (ink_hash_table_lookup(whc->post_data_ht, "Delete Snapshot", (void **) &snap_action)) {
+    if (ink_hash_table_lookup(whc->post_data_ht, "restore_delete_name", (void **) &snap_name)) {
+      if (strcmp(snap_name, "- select a snapshot -")) {
+        RecGetRecordString_Xmalloc("proxy.config.snapshot_dir", &snapDirFromRecordsConf);
+        ink_release_assert(found);
+        if (snapDirFromRecordsConf[0] != '/') {
+          char *snap_dir_cpy = xstrdup(snapDirFromRecordsConf);
+          ink_assert(snap_dir_cpy);
+          int newLen;
+          newLen = strlen(snap_dir_cpy) + strlen(config_dir) + 2;
+          snapDirFromRecordsConf = new char[newLen];
+          ink_assert(snapDirFromRecordsConf != NULL);
+          snprintf(snapDirFromRecordsConf, newLen, "%s%s%s", config_dir, DIR_SEP, snap_dir_cpy);
+          if (snap_dir_cpy)
+            free(snap_dir_cpy);
+        }
+        snap_result = configFiles->removeSnap(snap_name, snapDirFromRecordsConf);
+        if (snap_result < 0) {
+          mgmt_log(stderr, "[WebHttp::handle_submit_snapshot_to_filesystem] Remove snapshot failed");
+        }
+      }
+    }
+  }
+
+
+
+Ldone:
+  if (submit_from_page) {
+    err = WebHttpRender(whc, submit_from_page);
+    xfree(submit_from_page);
+  } else {
+    err = WebHttpRender(whc, HTML_DEFAULT_CONFIGURE_FILE);
+  }
+  return err;
+}
+
+
+//-------------------------------------------------------------------------
+// handle_submit_inspector
+//-------------------------------------------------------------------------
+static int
+handle_submit_inspector(WebHttpContext * whc, const char *file)
+{
+  NOWARN_UNUSED(file);
+  int err = 0;
+  char *submit_from_page;
+  char *regex;
+  char *regex_action;
+  char *list;
+
+  // check for submit_from_page
+  if (ink_hash_table_lookup(whc->post_data_ht, "submit_from_page", (void **) &submit_from_page)) {
+    ink_hash_table_delete(whc->post_data_ht, "submit_from_page");
+    whc->top_level_render_file = xstrdup(submit_from_page);
+  } else {
+    submit_from_page = NULL;
+  }
+
+  // FIXME: button names here are going to be hard to
+  // internationalize.  we should put the button names into the
+  // dictionary.
+
+  // handle URL Regex operation
+  if (ink_hash_table_lookup(whc->post_data_ht, "regex_op", (void **) &regex_action)) {
+    if (strcmp(regex_action, "Lookup") == 0) {
+      // handle regex lookup
+      if (ink_hash_table_lookup(whc->post_data_ht, "regex", (void **) &regex)) {
+        if ((err = INKLookupFromCacheUrlRegex(regex, &list)) == INK_ERR_OKAY) {
+          whc->cache_query_result = list;
+        }
+      }
+    } else if (strcmp(regex_action, "Delete") == 0) {
+      // handle regex delete
+      if (ink_hash_table_lookup(whc->post_data_ht, "regex", (void **) &regex)) {
+        if ((err = INKDeleteFromCacheUrlRegex(regex, &list)) == INK_ERR_OKAY) {
+          whc->cache_query_result = list;
+        }
+      }
+    } else if (strcmp(regex_action, "Invalidate") == 0) {
+      // handle regex invalidate
+      if (ink_hash_table_lookup(whc->post_data_ht, "regex", (void **) &regex)) {
+        if ((err = INKInvalidateFromCacheUrlRegex(regex, &list)) == INK_ERR_OKAY) {
+          whc->cache_query_result = list;
+        }
+      }
+    }
+  }
+  // Error: unknown action
+  else {
+    mgmt_log(stderr, "Unknown action is specified.");
+  }
+
+  if (err != INK_ERR_OKAY) {
+    // FIXME: show alarm error for cache inspector!
+  }
+
+  if (submit_from_page) {
+    err = WebHttpRender(whc, submit_from_page);
+    xfree(submit_from_page);
+  } else {
+    err = WebHttpRender(whc, HTML_DEFAULT_CONFIGURE_FILE);
+  }
+  return err;
+}
+
+
+//-------------------------------------------------------------------------
+// handle_submit_inspector_display
+//-------------------------------------------------------------------------
+
+static int
+handle_submit_inspector_display(WebHttpContext * whc, const char *file)
+{
+  NOWARN_UNUSED(file);
+  int err = 0;
+  char *url;
+  char *url_action;
+  char *buf;
+  InkHashTable *ht;
+  InkHashTable *query_ht;
+
+  // processFormSubmission will substituteUnsafeChars()
+  ht = whc->query_data_ht;
+  // extract some basic info for easier access later
+  if (ink_hash_table_lookup(ht, "url_op", (void **) &url_action)) {
+    // handle URL operation
+    if (strcmp(url_action, "Lookup") == 0) {
+      // handle url lookup
+      if (ink_hash_table_lookup(ht, "url", (void **) &url)) {
+        if ((err = INKLookupFromCacheUrl(url, &buf)) == INK_ERR_OKAY) {
+          whc->cache_query_result = buf;
+        }
+      }
+    } else if (strcmp(url_action, "Delete") == 0) {
+      // the url that cache_inspector takes has to be w/o substituteUnsafeChars()
+      if ((query_ht = processFormSubmission_noSubstitute((char *) (whc->request->getQuery()))) != NULL) {
+        if (ink_hash_table_lookup(query_ht, "url", (void **) &url)) {
+          // handle url delete
+          if ((err = INKDeleteFromCacheUrl(url, &buf)) == INK_ERR_OKAY) {
+            whc->cache_query_result = buf;
+          }
+        }
+        ink_hash_table_destroy_and_xfree_values(query_ht);
+      }
+    }
+  }
+  // Error: unknown action
+  else {
+    mgmt_log(stderr, "Unknown action is specified.");
+  }
+
+  err = WebHttpRender(whc, HTML_INSPECTOR_DISPLAY_FILE);
+  return err;
+}
 
 //-------------------------------------------------------------------------
 // handle_submit_view_logs
@@ -876,6 +1629,352 @@ Ldone:
   return err;
 }
 
+//-------------------------------------------------------------------------
+// handle_submit_update
+//-------------------------------------------------------------------------
+
+static int
+handle_submit_update(WebHttpContext * whc, const char *file)
+{
+  NOWARN_UNUSED(file);
+  int err;
+  char *submit_from_page;
+  bool recs_out_of_date;
+  bool file_out_of_date;
+  char *record_version;
+  char *file_version;
+  char *file_contents;
+  char *file_checksum;
+  char *apply;
+  char *cancel;
+  char *clear;
+  char *clear_cluster;
+  bool use_ssl_updated;
+
+  // check for submit_from_page
+  if (ink_hash_table_lookup(whc->post_data_ht, "submit_from_page", (void **) &submit_from_page)) {
+    ink_hash_table_delete(whc->post_data_ht, "submit_from_page");
+    whc->top_level_render_file = xstrdup(submit_from_page);
+  } else {
+    submit_from_page = NULL;
+  }
+
+  // check for cancel
+  if (ink_hash_table_lookup(whc->post_data_ht, "cancel", (void **) &cancel)) {
+    goto Ldone;
+  }
+  // check for restart
+  if (ink_hash_table_lookup(whc->post_data_ht, "restart", (void **) &cancel)) {
+#if TS_HAS_WEBUI
+    char *link = WebHttpGetLink_Xmalloc(HTML_DEFAULT_CONFIGURE_FILE);
+    whc->response_hdr->setRefreshURL(link);
+    xfree(link);
+#endif
+    lmgmt->ccom->sendClusterMessage(CLUSTER_MSG_SHUTDOWN_MANAGER);
+    whc->response_hdr->setRefresh(15);
+    if (submit_from_page)
+      xfree(submit_from_page);
+    submit_from_page = xstrdup("/restart.ink");
+    goto Ldone;
+  }
+  // check for clear statistics
+  if (ink_hash_table_lookup(whc->post_data_ht, "clear_stats", (void **) &clear)) {
+    lmgmt->clearStats();
+    goto Ldone;
+  }
+  // check for cluster clear statistics
+  if (ink_hash_table_lookup(whc->post_data_ht, "clear_cluster_stats", (void **) &clear_cluster)) {
+    lmgmt->clearStats();
+    lmgmt->ccom->sendClusterMessage(CLUSTER_MSG_CLEAR_STATS);
+    goto Ldone;
+  }
+  // check for roll_logs
+  if (ink_hash_table_lookup(whc->post_data_ht, "roll_logs", (void **) &cancel)) {
+    lmgmt->rollLogFiles();
+    goto Ldone;
+  }
+  // check for apply
+  if (ink_hash_table_lookup(whc->post_data_ht, "apply", (void **) &apply)) {
+    ink_hash_table_delete(whc->post_data_ht, "apply");
+    xfree(apply);
+  }
+  // check for record_version
+  recs_out_of_date = true;
+  if (ink_hash_table_lookup(whc->post_data_ht, "record_version", (void **) &record_version)) {
+    // TODO: Check return value?
+    recs_out_of_date = !record_version_valid(record_version);
+    ink_hash_table_delete(whc->post_data_ht, "record_version");
+    xfree(record_version);
+  }
+  // check for a file_version and file_contents
+  file_out_of_date = false;
+  if (ink_hash_table_lookup(whc->post_data_ht, "file_version", (void **) &file_version)) {
+    if (ink_hash_table_lookup(whc->post_data_ht, "file_contents", (void **) &file_contents)) {
+      file_out_of_date = true;
+      if (ink_hash_table_lookup(whc->post_data_ht, "file_checksum", (void **) &file_checksum)) {
+        if (!file_version) {
+          file_version = (char *) xstrdup("");
+        }
+        if (!file_contents) {
+          file_contents = (char *) xstrdup("");
+        }
+        if (!file_checksum) {
+          file_checksum = (char *) xstrdup("");
+        }
+        file_out_of_date = !set_config_file(whc, file_version, file_contents, file_checksum);
+        ink_hash_table_delete(whc->post_data_ht, "file_checksum");
+        if (file_checksum)
+          xfree(file_checksum);
+      }
+      ink_hash_table_delete(whc->post_data_ht, "file_contents");
+      if (file_contents)
+        xfree(file_contents);
+    }
+    ink_hash_table_delete(whc->post_data_ht, "file_version");
+    if (file_version)
+      xfree(file_version);
+  }
+  // everything else should be records. if the user modifies the
+  // 'proxy.config.admin.use_ssl' variable, we'll have to redirect
+  // them appropriately.
+  use_ssl_updated = false;
+  if (!recs_out_of_date) {
+    InkHashTableIteratorState htis;
+    InkHashTableEntry *hte;
+    char *record;
+    char *value;
+    for (hte = ink_hash_table_iterator_first(whc->post_data_ht, &htis);
+         hte != NULL; hte = ink_hash_table_iterator_next(whc->post_data_ht, &htis)) {
+      record = (char *) ink_hash_table_entry_key(whc->post_data_ht, hte);
+      value = (char *) ink_hash_table_entry_value(whc->post_data_ht, hte);
+      // check for ssl redirect
+      if (strcasecmp(record, "proxy.config.admin.use_ssl") == 0) {
+        char use_ssl_value[MAX_VAL_LENGTH];     // The value of the current variable
+        if ((varStrFromName(record, use_ssl_value, MAX_VAL_LENGTH)) && (ink_atoi(value) != ink_atoi(use_ssl_value))
+          ) {
+          use_ssl_updated = true;
+        }
+      }
+    }
+  }
+  // warn if out of date submission
+  if (recs_out_of_date || file_out_of_date) {
+    HtmlRndrText(whc->submit_warn, whc->lang_dict_ht, HTML_ID_OUT_OF_DATE);
+    HtmlRndrBr(whc->submit_warn);
+    whc->request_state |= WEB_HTTP_STATE_SUBMIT_WARN;
+  }
+
+  if (use_ssl_updated) {
+    if (submit_from_page) {
+      xfree(submit_from_page);
+    }
+    submit_from_page = xstrdup("/ssl_redirect.ink");
+  }
+
+#if TS_HAS_WEBUI
+  if (submit_from_page && strcmp(submit_from_page, HTML_FEATURE_ON_OFF_FILE) == 0) {
+    WebHttpTreeRebuildJsTree();
+  }
+#endif
+
+Ldone:
+  if (submit_from_page) {
+    err = WebHttpRender(whc, submit_from_page);
+    xfree(submit_from_page);
+  } else {
+    err = WebHttpRender(whc, HTML_DEFAULT_CONFIGURE_FILE);
+  }
+  return err;
+
+}
+
+//-------------------------------------------------------------------------
+// handle_submit_update_config
+//-------------------------------------------------------------------------
+// This handler is called when submit a post form for Configuration File Editor.
+// Uses the hidden tag values to construct and write  new config file.
+// If the user presses Cancel, then it should also close
+// the current window without committing any changes. If hit "Apply", then
+// commits the changes before closing editor window.
+//    Since the Configuration File Editor opens in a separate window,
+// each time a user hits "Apply", we need to also update the table listing all
+// the config rules on the original tab page from which the File Editor window
+// was launched - the orignal page is refreshed regularly in order to keep the
+// the values in sync with the Configuration File Editor page (is there a
+// better way to do this??)
+//    The file parameter is not used in this handler because a generic
+// c_config_display.ink is used for all files. We determine which file
+// is being revised by using the filename tag that's passed in with the
+// GET request.
+static int
+handle_submit_update_config(WebHttpContext * whc, const char *file)
+{
+  NOWARN_UNUSED(file);
+  char **rules = NULL;
+  char name[10];                // "rule#"
+  char *close;
+  char *apply;
+  char *filename;
+  char *frecord;
+  INKFileNameT type;
+  int i, numRules = 0;
+  int err = WEB_HTTP_ERR_OKAY;
+  char *errBuff = NULL;
+
+  // check for close
+  if (ink_hash_table_lookup(whc->post_data_ht, "close", (void **) &close)) {
+    //goto Ldone;
+    return WEB_HTTP_ERR_OKAY;
+  }
+  // check for apply
+  if (ink_hash_table_lookup(whc->post_data_ht, "apply", (void **) &apply)) {
+    ink_hash_table_delete(whc->post_data_ht, "apply");
+    xfree(apply);
+  }
+  // This portion of the code handles parsing the hidden tags with all
+  // the current ruleList information; commits this information as new config file
+
+  // get the filename to create the INKCfgContext; do NOT delete the
+  // HTML_CONFIG_FILE_TAG entry because we need to use the filename
+  // binding to refresh the page
+  if (!ink_hash_table_lookup(whc->post_data_ht, HTML_CONFIG_FILE_TAG, (void **) &filename)) {
+    // ERROR: no config file specified!!
+    whc->response_hdr->setStatus(STATUS_NOT_FOUND);
+    WebHttpSetErrorResponse(whc, STATUS_NOT_FOUND);
+    goto Lerror;
+  }
+  // CONFIG-SPECIFIC
+  if (ink_hash_table_lookup(g_display_config_ht, filename, (void **) &type)) {
+
+    int maxRules = 0;
+    INKCfgContext ctx = INKCfgContextCreate(type);
+    if (ctx && (INKCfgContextGet(ctx) == INK_ERR_OKAY)) {
+      maxRules = INKCfgContextGetCount(ctx) + MAX_ADD_RULES;
+      INKCfgContextDestroy(ctx);
+    }
+
+    // read all the rules from the post form into an array of strings
+    numRules = 0;
+    if (maxRules > 0) {
+      rules = new char *[maxRules];
+      for (i = 0; i < maxRules; i++) {
+        memset(name, 0, 10);
+        snprintf(name, sizeof(name), "rule%d", i);
+
+        if (ink_hash_table_lookup(whc->post_data_ht, name, (void **) &(rules[i]))) {
+          // do not delete entry from table yet
+          if (rules[i])
+            numRules++;
+          else
+            break;              // exit because no more valid rules to read
+        }
+      }
+    }
+
+    switch (type) {
+    case INK_FNAME_CACHE_OBJ:
+      err = updateCacheConfig(rules, numRules, &errBuff);
+      break;
+    case INK_FNAME_HOSTING:
+      err = updateHostingConfig(rules, numRules, &errBuff);
+      break;
+    case INK_FNAME_ICP_PEER:
+      err = updateIcpConfig(rules, numRules, &errBuff);
+      break;
+    case INK_FNAME_IP_ALLOW:
+      err = updateIpAllowConfig(rules, numRules, &errBuff);
+      break;
+    case INK_FNAME_MGMT_ALLOW:
+      err = updateMgmtAllowConfig(rules, numRules, &errBuff);
+      break;
+    case INK_FNAME_PARENT_PROXY:
+      err = updateParentConfig(rules, numRules, &errBuff);
+      break;
+    case INK_FNAME_PARTITION:
+      err = updatePartitionConfig(rules, numRules, &errBuff);
+      break;
+    case INK_FNAME_REMAP:
+      err = updateRemapConfig(rules, numRules, &errBuff);
+      break;
+    case INK_FNAME_SOCKS:
+      err = updateSocksConfig(rules, numRules, &errBuff);
+      break;
+    case INK_FNAME_SPLIT_DNS:
+      err = updateSplitDnsConfig(rules, numRules, &errBuff);
+      break;
+    case INK_FNAME_UPDATE_URL:
+      err = updateUpdateConfig(rules, numRules, &errBuff);
+      break;
+    case INK_FNAME_VADDRS:
+      err = updateVaddrsConfig(rules, numRules, &errBuff);
+      break;
+    default:
+      err = WEB_HTTP_ERR_FAIL;
+      break;
+    }
+
+    // do not delete the strings in the array because
+    // the binding still exists in the hashtable, so memory will
+    // be freed when post_data_ht destroyed
+    if (rules)
+      delete[]rules;
+
+  } else {                      // missing binding from f_xx_config.ink to INKFileNameT
+    whc->response_hdr->setStatus(STATUS_NOT_FOUND);
+    WebHttpSetErrorResponse(whc, STATUS_NOT_FOUND);
+    goto Lerror;
+  }
+
+  if (err == WEB_HTTP_ERR_INVALID_CFG_RULE) {
+    whc->request_state |= WEB_HTTP_STATE_SUBMIT_WARN;
+    HtmlRndrText(whc->submit_warn, whc->lang_dict_ht, HTML_ID_CFG_INVALID_RULE);
+    HtmlRndrBr(whc->submit_warn);
+
+    if (errBuff) {
+      whc->submit_warn->copyFrom(errBuff, strlen(errBuff));
+      xfree(errBuff);
+    }
+  } else if (err != WEB_HTTP_ERR_OKAY) {
+    HtmlRndrText(whc->submit_warn, whc->lang_dict_ht, HTML_ID_CFG_COMMIT_ERROR);
+    HtmlRndrBr(whc->submit_warn);
+    whc->request_state |= WEB_HTTP_STATE_SUBMIT_WARN;
+  }
+  // do not remove and free frecord from post_data_ht because
+  // the renderer fn will use it to write the hidden tag
+  if (ink_hash_table_lookup(whc->post_data_ht, "frecord", (void **) &frecord)) {
+    if (recordRestartCheck(frecord)) {
+      ink_hash_table_insert(whc->submit_note_ht, frecord, NULL);
+      if (!(whc->request_state & WEB_HTTP_STATE_SUBMIT_NOTE)) {
+        HtmlRndrText(whc->submit_note, whc->lang_dict_ht, HTML_ID_RESTART_REQUIRED_FILE);
+        HtmlRndrBr(whc->submit_note);
+      }
+      whc->request_state |= WEB_HTTP_STATE_SUBMIT_NOTE;
+    }
+  }
+
+  err = WebHttpRender(whc, HTML_CONFIG_DISPLAY_FILE);
+  return err;
+
+Lerror:
+  mgmt_log("[handle_submit_update_config] Error updating config file");
+  return WEB_HTTP_ERR_REQUEST_ERROR;
+
+}
+
+//-------------------------------------------------------------------------
+// handle_submit_config_display
+//-------------------------------------------------------------------------
+// This handler is called when user wants to open the Configuration Editor
+// window to edit a config file; so it main purpose is simply to
+// render the configurator.ink page
+static int
+handle_submit_config_display(WebHttpContext * whc, const char *file)
+{
+  NOWARN_UNUSED(file);
+  // same HTML_CONFIG_DISPLAY_FILE for all config files
+  return WebHttpRender(whc, HTML_CONFIG_DISPLAY_FILE);
+}
+
 
 //-------------------------------------------------------------------------
 // network configuration
@@ -912,6 +2011,513 @@ SetWarning(WebHttpContext * whc, char *a
   whc->request_state |= WEB_HTTP_STATE_SUBMIT_WARN;
 }
 
+//-------------------------------------------------------------------------
+// handle_submit_net_config
+//-------------------------------------------------------------------------
+// This handler is called when user wants to setup network of the appliance
+
+static int
+handle_submit_net_config(WebHttpContext * whc, const char *file)
+{
+  NOWARN_UNUSED(file);
+  char *cancel;
+  char *record_version;
+  char *submit_from_page;
+//  FILE* tmp;
+
+//  tmp=fopen("tmp","a");
+//  fprintf(tmp,"enter submit\n");
+
+  if (ink_hash_table_lookup(whc->post_data_ht, "submit_from_page", (void **) &submit_from_page)) {
+    ink_hash_table_delete(whc->post_data_ht, "submit_from_page");
+    whc->top_level_render_file = xstrdup(submit_from_page);
+  } else {
+    submit_from_page = NULL;
+  }
+  // check for cancel
+  if (ink_hash_table_lookup(whc->post_data_ht, "cancel", (void **) &cancel))
+    return WebHttpRender(whc, submit_from_page);
+
+  // check for record_version
+  if (ink_hash_table_lookup(whc->post_data_ht, "record_version", (void **) &record_version)) {
+    // TODO: Check return value?
+    record_version_valid(record_version);
+    ink_hash_table_delete(whc->post_data_ht, "record_version");
+    xfree(record_version);
+  }
+//  if (recs_out_of_date)
+//    goto Lout_of_date;
+
+#if defined(linux) || defined(solaris)
+
+  InkHashTableIteratorState htis;
+  InkHashTableEntry *hte;
+  char *key;
+  char *value;
+  int hn_change, gw_change, dn_change, dns_change;
+  int nic_change[5];
+  //  int nic_up[5];
+  char *dns_ip[3], old_value[265], old_hostname[80], old_gw_ip[80];
+  char nic_name[5][10], *nic[5][6], interface[80], *param;
+  char *hostname = 0, *gw_ip = 0;
+  const char *dn = 0;
+  int i, j, no;
+  char dns_ips[80];
+  bool warning, fail;
+
+  //This will be used as flags to verify whether anything changed by the user
+  hn_change = 0;
+  gw_change = 0;
+  dn_change = 0;
+  dns_change = 0;
+  warning = (fail = false);
+  //FIXNOW - we need to use SysAPI to find the numver of NICs instead of just constant 5
+  for (i = 0; i < 5; i++) {
+    nic_change[i] = 0;
+    ink_strncpy(nic_name[i], "", 1);
+    for (j = 0; j < 6; j++) {
+      nic[i][j] = NULL;
+    }
+  }
+
+  int old_euid;
+  Config_User_Root(&old_euid);
+  // Get the values the user entered
+  for (hte = ink_hash_table_iterator_first(whc->post_data_ht, &htis);
+       hte != NULL; hte = ink_hash_table_iterator_next(whc->post_data_ht, &htis)) {
+    key = (char *) ink_hash_table_entry_key(whc->post_data_ht, hte);
+    value = (char *) ink_hash_table_entry_value(whc->post_data_ht, hte);
+
+//    fprintf(stderr,"key=%s, value=%s\n",key,value);
+
+    if (strcmp(key, "HOSTNAME") == 0) {
+      hostname = value;
+      if (!Net_IsValid_Hostname(hostname)) {
+        SetWarning(whc, key);
+        warning = true;
+      } else {
+        if (!Config_GetHostname(old_value, sizeof(old_value))) {
+          if (hostname != NULL && strcmp(hostname, old_value) != 0) {
+            hn_change = 1;
+            ink_strncpy(old_hostname, old_value, sizeof(old_hostname)); //old hostname is used in MGMT API
+          }
+        } else if (hostname != NULL) {
+          hn_change = 1;
+        }
+      }
+    } else if (strcmp(key, "GATEWAY") == 0) {
+      gw_ip = value;
+      if (!Net_IsValid_IP(gw_ip)) {
+        SetWarning(whc, key);
+        warning = true;
+      } else {
+        if (!Config_GetDefaultRouter(old_value, sizeof(old_value))) {
+          if (gw_ip != NULL && strcmp(gw_ip, old_value) != 0) {
+            ink_strncpy(old_gw_ip, old_value, sizeof(old_gw_ip));
+            gw_change = 1;
+          }
+        } else if (gw_ip != NULL) {
+          gw_change = 1;
+        }
+      }
+    } else if (strcmp(key, "domain") == 0) {
+      dn = value;
+      if (!Config_GetDomain(old_value, sizeof(old_value))) {
+        if (dn != NULL && strcmp(dn, old_value) != 0) {
+          dn_change = 1;
+        } else if (dn == NULL) {
+          dn_change = 1;
+          dn = "";
+        }
+      } else if (dn != NULL) {
+        dn_change = 1;
+      }
+    } else if (strstr(key, "DNS") != NULL) {
+      no = atoi(key + 3) - 1;
+      dns_ip[no] = value;
+      if (!Net_IsValid_IP(dns_ip[no])) {
+        SetWarning(whc, key);
+        warning = true;
+      } else {
+        if (Config_GetDNS_Server(old_value, sizeof(old_value), no)) {
+          if (dns_ip[no] != NULL && strcmp(dns_ip[no], old_value) != 0) {
+            dns_change = 1;
+          } else if (dns_ip[no] == NULL) {
+            dns_change = 1;
+          }
+        } else if (dns_ip[no] != NULL) {
+          dns_change = 1;
+        }
+      }
+    } else if (strstr(key, "NIC") != NULL) {
+      ink_strncpy(interface, key + 4, sizeof(interface));
+      param = strchr(interface, '_');
+      *param = '\0';
+      param++;
+      no = atoi(interface + 3);
+      ink_strncpy(nic_name[no], interface, sizeof(nic_name[no]));
+
+      //No DHCP support any more, hacking way is set it be static always
+      nic[no][2] = xstrdup("1");
+      if (strcmp(param, "enabled") == 0) {
+        nic[no][0] = value;
+
+        if (no == 0) {
+          //FIXNOW use SysAPI
+          if (strcmp(nic[no][0], "0") == 0) {
+            SetWarning(whc, key);
+            warning = true;
+          }
+        }
+        //FIXNOW - Use SysAPI
+        Config_GetNIC_Status(interface, old_value, sizeof(old_value));
+        if (strcmp(old_value, "up") == 0 && strcmp(nic[no][0], "0") == 0) {
+          nic_change[no] = 1;
+        } else if (strcmp(old_value, "down") == 0 && strcmp(nic[no][0], "1") == 0) {
+          nic_change[no] = 1;
+        }
+      } else if (strcmp(param, "ONBOOT") == 0) {
+        nic[no][1] = value;
+
+        if (no == 0) {
+          //FIXNOW use SysAPI
+          if (strcmp(nic[no][1], "0") == 0) {
+            SetWarning(whc, key);
+            warning = true;
+          }
+        }
+        //FIXNOW - Use SysAPI
+        if (!Config_GetNIC_Start(interface, old_value, sizeof(old_value))) {
+          if (strcmp(nic[no][1], "1") == 0 && strcmp(old_value, "not-onboot") == 0) {
+            nic_change[no] = 1;
+          } else if (strcmp(nic[no][1], "0") == 0 && strcmp(old_value, "onboot") == 0) {
+            nic_change[no] = 1;
+          }
+        } else {
+          nic_change[no] = 1;
+        }
+      } else if (strcmp(param, "BOOTPROTO") == 0) {
+        nic[no][2] = value;
+        //FIXNOW - Use SysAPI
+        if (!Config_GetNIC_Protocol(interface, old_value, sizeof(old_value))) {
+          if (strcmp(nic[no][2], "0") == 0 && (strcmp(old_value, "none") == 0 || strcmp(old_value, "static") == 0)) {
+            nic_change[no] = 1;
+          } else if (strcmp(nic[no][2], "1") == 0 && strcmp(old_value, "dhcp") == 0) {
+            nic_change[no] = 1;
+          }
+        } else {
+          nic_change[no] = 1;
+        }
+
+        //currently, force the protocol to become static if the old one is dhcp
+        if (strcmp(old_value, "dhcp") == 0) {
+          // XXX - changed it so we don't change value and instead duplicate the string
+          nic[no][2] = xstrdup("1");
+          nic_change[no] = 1;
+        }
+      } else if (strcmp(param, "IPADDR") == 0) {
+        nic[no][3] = value;
+        //FIXNOW - Use SysAPI
+        if (!Net_IsValid_IP(nic[no][3])) {
+          SetWarning(whc, key);
+          warning = true;
+        }
+        //FIXNOW - Use SysAPI
+        if (!Config_GetNIC_IP(interface, old_value, sizeof(old_value))) {
+          if (nic[no][3] != NULL && strcmp(nic[no][3], old_value) != 0) {
+            nic_change[no] = 1;
+          }
+          //For dhcp start, the static IP maybe same with the dhcp value
+          else {
+            char protocol[80];
+            Config_GetNIC_Protocol(interface, protocol, sizeof(protocol));
+            if (strcmp(protocol, "dhcp") == 0) {
+              nic_change[no] = 1;
+            }
+
+            if (nic[no][3] == NULL) {
+              nic_change[no] = 1;
+            }
+          }
+        } else if (nic[no][3] != NULL) {
+          nic_change[no] = 1;
+        }
+      } else if (strcmp(param, "NETMASK") == 0) {
+        nic[no][4] = value;
+        //FIXNOW - Use SysAPI
+        if (!Net_IsValid_IP(nic[no][4])) {
+          SetWarning(whc, key);
+          warning = true;
+        }
+        //FIXNOW - Use SysAPI
+        if (!Config_GetNIC_Netmask(interface, old_value, sizeof(old_value))) {
+          if (nic[no][4] != NULL && strcmp(nic[no][4], old_value) != 0) {
+            nic_change[no] = 1;
+          }
+          //For dhcp start, the static netmask maybe same with the dhcp value
+          else {
+            char protocol[80];
+            Config_GetNIC_Protocol(interface, protocol, sizeof(protocol));
+            if (strcmp(protocol, "dhcp") == 0) {
+              nic_change[no] = 1;
+            }
+
+            if (nic[no][4] == NULL) {
+              nic_change[no] = 1;
+            }
+          }
+        } else if (nic[no][4] != NULL) {
+          nic_change[no] = 1;
+        }
+      } else if (strcmp(param, "GATEWAY") == 0) {
+        nic[no][5] = value;
+        //FIXNOW - Use SysAPI
+        if (!Net_IsValid_IP(nic[no][5])) {
+          SetWarning(whc, key);
+          warning = true;
+        }
+        //FIXNOW - Use SysAPI
+        if (!Config_GetNIC_Gateway(interface, old_value, sizeof(old_value))) {
+          if (nic[no][5] != NULL && strcmp(nic[no][5], old_value) != 0) {
+            nic_change[no] = 1;
+          }
+          //For dhcp start, the gateway maybe same with the dhcp value
+          else {
+            char protocol[80];
+            Config_GetNIC_Protocol(interface, protocol, sizeof(protocol));
+            if (strcmp(protocol, "dhcp") == 0) {
+              nic_change[no] = 1;
+            }
+
+            if (nic[no][5] == NULL) {
+              nic_change[no] = 1;
+            }
+          }
+        } else if (nic[no][5] != NULL) {
+          nic_change[no] = 1;
+        }
+      }
+    }
+  }
+  Config_User_Inktomi(old_euid);
+
+  if (!warning) {
+    if (hn_change) {
+      if (Config_SetHostname(hostname) != 0) {
+        fail = true;
+      }
+    }
+    if (gw_change) {
+      if (Config_SetDefaultRouter(gw_ip) != 0) {
+        fail = true;
+      }
+    }
+    if (dn_change) {
+      if (Config_SetDomain(dn) != 0) {
+        fail = true;
+      }
+    }
+    if (dns_change) {
+      ink_strncpy(dns_ips, "", sizeof(dns_ips));
+      //FIXNOW - do we have no. of dns servers from SysAPI?
+      for (i = 0; i < 3; i++) {
+        if (dns_ip[i] != NULL) {
+          strncat(dns_ips, dns_ip[i], sizeof(dns_ips) - strlen(dns_ips) - 1);
+          strncat(dns_ips, " ", sizeof(dns_ips) - strlen(dns_ips) - 1);
+        }
+      }
+
+      if (Config_SetDNS_Servers(dns_ips) != 0) {
+        fail = true;
+      }
+    }
+    //FIXNOW - get the no. from SysAPI
+    for (i = 0; i < 5; i++) {
+      if (strlen(nic_name[i]) != 0) {
+        if (nic_change[i]) {
+          if (nic[i][0] != NULL && strcmp(nic[i][0], "1") == 0) {
+            char onboot[20], protocol[20];
+            if (strcmp(nic[i][1], "1") == 0) {
+              ink_strncpy(onboot, "onboot", sizeof(onboot));
+            } else {
+              ink_strncpy(onboot, "not-onboot", sizeof(onboot));
+            }
+
+            if (strcmp(nic[i][2], "1") == 0) {
+              ink_strncpy(protocol, "static", sizeof(protocol));
+            } else {
+              ink_strncpy(protocol, "dhcp", sizeof(protocol));
+            }
+            if (Config_SetNIC_Up(nic_name[i], onboot, protocol, nic[i][3], nic[i][4], nic[i][5]) != 0) {
+              fail = true;
+            }
+          } else {
+            char status[80];
+            Config_GetNIC_Status(nic_name[i], status, sizeof(status));
+            if (strcmp(status, "up") == 0) {    //NIC is disabled
+              if (Config_SetNIC_Down(nic_name[i]) != 0) {
+                fail = true;
+              }
+            } else {            //NIC is down&changed, such changes are disallowed.
+              if (!(whc->request_state & WEB_HTTP_STATE_SUBMIT_WARN)) {
+                HtmlRndrText(whc->submit_warn, whc->lang_dict_ht, HTML_ID_NETWORK_CONFIG_DISALLOW);
+                HtmlRndrBr(whc->submit_warn);
+              }
+              whc->request_state |= WEB_HTTP_STATE_SUBMIT_WARN;
+            }
+          }                     //nic[i][0]
+        }                       //nic_change
+      }                         //nic_name
+    }                           //for
+  }                             //warning
+//FIXME, need a complete fail message system
+  if (fail == true) {
+    if (!(whc->request_state & WEB_HTTP_STATE_SUBMIT_WARN)) {
+      HtmlRndrText(whc->submit_warn, whc->lang_dict_ht, HTML_ID_NETWORK_CONFIG_FAIL);
+      HtmlRndrBr(whc->submit_warn);
+    }
+    whc->request_state |= WEB_HTTP_STATE_SUBMIT_WARN;
+  }
+
+  if (hn_change) {
+    if (submit_from_page)
+      xfree(submit_from_page);
+    submit_from_page = xstrdup("/rename.ink");
+  }
+#endif
+  return WebHttpRender(whc, submit_from_page);
+}
+
+
+//-------------------------------------------------------------------------
+// handle_default
+//-------------------------------------------------------------------------
+
+static int
+handle_default(WebHttpContext * whc, const char *file)
+{
+
+  char *doc_root_file;
+  int file_size;
+  time_t file_date_gmt;
+  WebHandle h_file;
+
+  httpMessage *request = whc->request;
+  httpResponse *response_hdr = whc->response_hdr;
+  textBuffer *response_bdy = whc->response_bdy;
+
+  const char *request_file = file;
+  time_t request_file_ims;
+  int request_file_len;
+
+  // requests are supposed to begin with a "/"
+  if (*request_file != '/') {
+    response_hdr->setStatus(STATUS_NOT_FOUND);
+    WebHttpSetErrorResponse(whc, STATUS_NOT_FOUND);
+    return WEB_HTTP_ERR_REQUEST_ERROR;
+  }
+  // first, make sure there are no ..'s in path or root directory
+  // access in name for security reasons
+  if (strstr(request_file, "..") != NULL || strncmp(request_file, "//", 2) == 0) {
+    response_hdr->setStatus(STATUS_FORBIDDEN);
+    WebHttpSetErrorResponse(whc, STATUS_FORBIDDEN);
+    return WEB_HTTP_ERR_REQUEST_ERROR;
+  }
+
+  if (strcmp("/", request_file) == 0) {
+    request_file = whc->default_file;
+  }
+  // check file type and set document type if appropiate
+  request_file_len = strlen(request_file);
+  if (strcmp(request_file + (request_file_len - 4), ".htm") == 0) {
+    response_hdr->setContentType(TEXT_HTML);
+  } else if (strcmp(request_file + (request_file_len - 5), ".html") == 0) {
+    response_hdr->setContentType(TEXT_HTML);
+  } else if (strcmp(request_file + (request_file_len - 4), ".css") == 0) {
+    response_hdr->setContentType(TEXT_CSS);
+  } else if (strcmp(request_file + (request_file_len - 4), ".gif") == 0) {
+    response_hdr->setContentType(IMAGE_GIF);
+  } else if (strcmp(request_file + (request_file_len - 4), ".jpg") == 0) {
+    response_hdr->setContentType(IMAGE_JPEG);
+  } else if (strcmp(request_file + (request_file_len - 5), ".jpeg") == 0) {
+    response_hdr->setContentType(IMAGE_JPEG);
+  } else if (strcmp(request_file + (request_file_len - 4), ".png") == 0) {
+    response_hdr->setContentType(IMAGE_PNG);
+  } else if (strcmp(request_file + (request_file_len - 4), ".jar") == 0) {
+    response_hdr->setContentType(APP_JAVA);
+  } else if (strcmp(request_file + (request_file_len - 3), ".js") == 0) {
+    response_hdr->setContentType(APP_JAVASCRIPT);
+  } else if (strcmp(request_file + (request_file_len - 4), ".der") == 0) {
+    response_hdr->setContentType(APP_X509);
+  } else if (strcmp(request_file + (request_file_len - 4), ".dat") == 0) {
+    response_hdr->setContentType(APP_AUTOCONFIG);
+    response_hdr->setCachable(0);
+  } else if (strcmp(request_file + (request_file_len - 4), ".pac") == 0) {
+    response_hdr->setContentType(APP_AUTOCONFIG);
+    // Fixed INKqa04312 - 02/21/1999 elam
+    // We don't want anyone to cache .pac files.
+    response_hdr->setCachable(0);
+  } else if (strcmp(request_file + (request_file_len - 4), ".zip") == 0) {
+    response_hdr->setContentType(APP_ZIP);
+  } else {
+    // don't serve file types that we don't know about; helps to lock
+    // down the webserver.  for example, when serving files out the
+    // etc/trafficserver/plugins directory, we don't want to allow the users to
+    // access the .so/.dll plugin files.
+    response_hdr->setStatus(STATUS_NOT_FOUND);
+    WebHttpSetErrorResponse(whc, STATUS_NOT_FOUND);
+    return WEB_HTTP_ERR_REQUEST_ERROR;
+  }
+
+  // append the appropriate doc_root on to the file
+  doc_root_file = WebHttpAddDocRoot_Xmalloc(whc, request_file);
+
+  // open the requested file
+  if ((h_file = WebFileOpenR(doc_root_file)) == WEB_HANDLE_INVALID) {
+    //could not find file
+    xfree(doc_root_file);
+    response_hdr->setStatus(STATUS_NOT_FOUND);
+    WebHttpSetErrorResponse(whc, STATUS_NOT_FOUND);
+    return WEB_HTTP_ERR_REQUEST_ERROR;
+  }
+  // get the file
+  file_size = WebFileGetSize(h_file);
+  file_date_gmt = WebFileGetDateGmt(h_file);
+  request_file_ims = request->getModTime();
+
+  // special logic for the autoconf port
+  if ((whc->server_state & WEB_HTTP_SERVER_STATE_AUTOCONF) && (file_size == 0)) {
+    response_hdr->setStatus(STATUS_NOT_FOUND);
+    WebHttpSetErrorResponse(whc, STATUS_NOT_FOUND);
+    WebFileClose(h_file);
+    xfree(doc_root_file);
+    return WEB_HTTP_ERR_REQUEST_ERROR;
+  }
+  // Check to see if the clients copy is up to date.  Ignore the
+  // stupid content length that Netscape Navigator sends on the
+  // If-Modified-Since line since it not in the HTTP 1.0 standard
+
+  // Since the client sends If-Modified-Since in GMT, make sure that
+  // we transform mtime to GMT
+  if (request_file_ims != -1 && request_file_ims >= file_date_gmt) {
+    response_hdr->setStatus(STATUS_NOT_MODIFIED);
+  } else {
+    // fetch the file from disk to memory
+    response_hdr->setStatus(STATUS_OK);
+    response_hdr->setLength(file_size);
+    while (response_bdy->rawReadFromFile(h_file) > 0);
+  }
+  // set the document last-modified header
+  response_hdr->setLastMod(file_date_gmt);
+
+  WebFileClose(h_file);
+  xfree(doc_root_file);
+
+  return WEB_HTTP_ERR_OKAY;
+
+}
+
+
 
 //-------------------------------------------------------------------------
 // read_request
@@ -1200,10 +2806,22 @@ WebHttpInit()
   // initialize submit bindings
   g_submit_bindings_ht = ink_hash_table_create(InkHashTableKeyType_String);
   ink_hash_table_insert(g_submit_bindings_ht, HTML_SUBMIT_ALARM_FILE, (void *) handle_submit_alarm);
+  ink_hash_table_insert(g_submit_bindings_ht, HTML_SUBMIT_MGMT_AUTH_FILE, (void *) handle_submit_mgmt_auth);
+  //ink_hash_table_insert(g_submit_bindings_ht, HTML_SUBMIT_SNAPSHOT_FILE, handle_submit_snapshot);
+  ink_hash_table_insert(g_submit_bindings_ht, HTML_SUBMIT_SNAPSHOT_FILESYSTEM,
+                        (void *) handle_submit_snapshot_to_filesystem);
+  ink_hash_table_insert(g_submit_bindings_ht, HTML_SUBMIT_INSPECTOR_FILE, (void *) handle_submit_inspector);
+  ink_hash_table_insert(g_submit_bindings_ht, HTML_SUBMIT_INSPECTOR_DPY_FILE, (void *) handle_submit_inspector_display);
   ink_hash_table_insert(g_submit_bindings_ht, HTML_SUBMIT_VIEW_LOGS_FILE, (void *) handle_submit_view_logs);
+  ink_hash_table_insert(g_submit_bindings_ht, HTML_SUBMIT_UPDATE_FILE, (void *) handle_submit_update);
+  ink_hash_table_insert(g_submit_bindings_ht, HTML_SUBMIT_UPDATE_CONFIG, (void *) handle_submit_update_config);
+  ink_hash_table_insert(g_submit_bindings_ht, HTML_SUBMIT_CONFIG_DISPLAY, (void *) handle_submit_config_display);
+  ink_hash_table_insert(g_submit_bindings_ht, HTML_SUBMIT_NET_CONFIG, (void *) handle_submit_net_config);
   // initialize file bindings
   g_file_bindings_ht = ink_hash_table_create(InkHashTableKeyType_String);
   ink_hash_table_insert(g_file_bindings_ht, HTML_CHART_FILE, (void *) handle_chart);
+  ink_hash_table_insert(g_file_bindings_ht, HTML_BACKDOOR_CONFIG_FILES, (void *) handle_config_files);
+  ink_hash_table_insert(g_file_bindings_ht, HTML_BACKDOOR_DEBUG_LOGS, (void *) handle_debug_logs);
   ink_hash_table_insert(g_file_bindings_ht, HTML_SYNTHETIC_FILE, (void *) handle_synthetic);
 
   // initialize extension bindings
@@ -1215,17 +2833,209 @@ WebHttpInit()
   // configurator display filename (eg. f_cache_config.ink) to
   // its mgmt API config file type (INKFileNameT)
   g_display_config_ht = ink_hash_table_create(InkHashTableKeyType_String);
+  ink_hash_table_insert(g_display_config_ht, HTML_FILE_CACHE_CONFIG, (void *) INK_FNAME_CACHE_OBJ);
+  ink_hash_table_insert(g_display_config_ht, HTML_FILE_HOSTING_CONFIG, (void *) INK_FNAME_HOSTING);
+  ink_hash_table_insert(g_display_config_ht, HTML_FILE_ICP_CONFIG, (void *) INK_FNAME_ICP_PEER);
+  ink_hash_table_insert(g_display_config_ht, HTML_FILE_IP_ALLOW_CONFIG, (void *) INK_FNAME_IP_ALLOW);
+  ink_hash_table_insert(g_display_config_ht, HTML_FILE_MGMT_ALLOW_CONFIG, (void *) INK_FNAME_MGMT_ALLOW);
+  ink_hash_table_insert(g_display_config_ht, HTML_FILE_PARENT_CONFIG, (void *) INK_FNAME_PARENT_PROXY);
+  ink_hash_table_insert(g_display_config_ht, HTML_FILE_PARTITION_CONFIG, (void *) INK_FNAME_PARTITION);
+  ink_hash_table_insert(g_display_config_ht, HTML_FILE_REMAP_CONFIG, (void *) INK_FNAME_REMAP);
+  ink_hash_table_insert(g_display_config_ht, HTML_FILE_SOCKS_CONFIG, (void *) INK_FNAME_SOCKS);
+  ink_hash_table_insert(g_display_config_ht, HTML_FILE_SPLIT_DNS_CONFIG, (void *) INK_FNAME_SPLIT_DNS);
+  ink_hash_table_insert(g_display_config_ht, HTML_FILE_UPDATE_CONFIG, (void *) INK_FNAME_UPDATE_URL);
+  ink_hash_table_insert(g_display_config_ht, HTML_FILE_VADDRS_CONFIG, (void *) INK_FNAME_VADDRS);
 
   // initialize other modules
   WebHttpAuthInit();
+  WebHttpLogInit();
+  WebHttpSessionInit();
 #if TS_HAS_WEBUI
   WebHttpRenderInit();
+  WebHttpTreeInit();
 #endif
 
   return;
 }
 
 //-------------------------------------------------------------------------
+// WebHttpHandleConnection
+//
+// Handles http requests across the web management port
+//-------------------------------------------------------------------------
+
+void
+WebHttpHandleConnection(WebHttpConInfo * whci)
+{
+
+  int err = WEB_HTTP_ERR_OKAY;
+
+  WebHttpContext *whc;
+  WebHttpHandler handler;
+  char *file;
+  char *extn;
+  int drain_bytes;
+  char ch;
+
+  // initialization
+  if ((whc = WebHttpContextCreate(whci)) == NULL)
+    goto Ltransaction_close;
+  if (signal_handler_init() != WEB_HTTP_ERR_OKAY)
+    goto Ltransaction_close;
+  if (whc->server_state & WEB_HTTP_SERVER_STATE_SSL_ENABLED)
+    if (ssl_init(whc) != WEB_HTTP_ERR_OKAY)
+      goto Ltransaction_close;
+
+  // read request
+  if ((err = read_request(whc)) != WEB_HTTP_ERR_OKAY)
+    goto Lerror_switch;
+
+  // authentication
+  if (whc->server_state & WEB_HTTP_SERVER_STATE_AUTH_ENABLED)
+    if (WebHttpAuthenticate(whc) != WEB_HTTP_ERR_OKAY)
+      goto Ltransaction_send;
+
+  // get our file information
+  file = (char *) (whc->request->getFile());
+  if (strcmp("/", file) == 0) {
+    file = (char *) (whc->default_file);
+  }
+
+  Debug("web2", "[WebHttpHandleConnection] request file: %s", file);
+
+
+  if (whc->server_state & WEB_HTTP_SERVER_STATE_AUTOCONF) {
+
+    // security concern: special treatment if we're handling a request
+    // on the autoconf port.  can't have users downloading arbitrary
+    // files under the config directory!
+    if (!ink_hash_table_isbound(g_autoconf_allow_ht, file)) {
+      mgmt_elog(stderr,"[WebHttpHandleConnection] %s not valid autoconf file",file);
+      whc->response_hdr->setStatus(STATUS_NOT_FOUND);
+      WebHttpSetErrorResponse(whc, STATUS_NOT_FOUND);
+      goto Ltransaction_send;
+    }
+  } else {
+#if TS_HAS_WEBUI
+    if (WebHttpTreeReturnRefresh(file)) {
+      // if we are handling a monitor/mrtg page, configure it to refresh
+      if (strncmp(file, "/monitor/", 9) == 0) {
+        whc->response_hdr->setRefresh(wGlobals.refreshRate);
+      } else if (strncmp(file, "/mrtg/", 6) == 0) {
+        whc->response_hdr->setRefresh(REFRESH_RATE_MRTG);
+      } else {                  // default
+        whc->response_hdr->setRefresh(wGlobals.refreshRate);
+      }
+    }
+#endif
+    // Make a note if we are a plugin.  Being a plugin will affect our
+    // doc_root and how request files and doc_roots are joined to
+    // generate an absolute path.  See WebHttpAddDocRoot_Xmalloc()
+    if (strncmp(file, "/plugins/", 9) == 0) {
+      whc->request_state |= WEB_HTTP_STATE_PLUGIN;
+    }
+
+  }
+
+  // process query
+  process_query(whc);
+
+  // check submit_binding;
+  // if nothing, check file_binding;
+  // if nothing, check extn_binding;
+  // if still nothing, use the default handler;
+  if (ink_hash_table_lookup(g_submit_bindings_ht, file, (void **) &handler)) {
+    // workaround: sometimes we receive a GET for our submit cgi's
+    // (rather than a resubmitted POST).  In this case, just render
+    // the default page since we can't do much else
+    if (whc->request->getMethod() != METHOD_POST) {
+      if ((strcmp(file, HTML_SUBMIT_INSPECTOR_DPY_FILE) != 0) && (strcmp(file, HTML_SUBMIT_CONFIG_DISPLAY) != 0)) {
+        err = WebHttpRender(whc, HTML_DEFAULT_MONITOR_FILE);
+        goto Lerror_switch;
+      }
+    }
+    // process post
+    process_post(whc);
+    // only allow one submission at a time
+    ink_mutex_acquire(&wGlobals.submitLock);
+    err = handler(whc, file);
+    ink_mutex_release(&wGlobals.submitLock);
+  } else {
+    if (!ink_hash_table_lookup(g_file_bindings_ht, file, (void **) &handler)) {
+      extn = file;
+      while (*extn != '\0')
+        extn++;
+      while ((extn > file) && (*extn != '.'))
+        extn--;
+      if (!ink_hash_table_lookup(g_extn_bindings_ht, extn, (void **) &handler)) {
+        handler = handle_default;
+      }
+    }
+    err = handler(whc, file);
+  }
+
+Lerror_switch:
+
+  switch (err) {
+  case WEB_HTTP_ERR_OKAY:
+  case WEB_HTTP_ERR_REQUEST_ERROR:
+    goto Ltransaction_send;
+  case WEB_HTTP_ERR_FAIL:
+  case WEB_HTTP_ERR_REQUEST_FATAL:
+  default:
+    goto Ltransaction_close;
+  }
+
+Ltransaction_send:
+
+  // write response
+  if ((err = write_response(whc)) != WEB_HTTP_ERR_OKAY)
+    goto Ltransaction_close;
+
+  // close the connection before logging it to reduce latency
+#ifndef _WIN32
+  shutdown(whc->si.fd, 1);
+  drain_bytes = 0;
+  if (fcntl(whc->si.fd, F_SETFL, O_NONBLOCK) >= 0) {
+    while ((read(whc->si.fd, &ch, 1) > 0) && (drain_bytes < MAX_DRAIN_BYTES)) {
+      drain_bytes++;
+    }
+  }
+#endif
+  close_socket(whc->si.fd);
+  whc->si.fd = -1;
+
+  // log transaction
+  if (wGlobals.logFD >= 0)
+    WebHttpLogTransaction(whc);
+
+Ltransaction_close:
+
+  // if we didn't close already, close connection
+  if (whc->si.fd != -1) {
+#ifndef _WIN32
+    shutdown(whc->si.fd, 1);
+    drain_bytes = 0;
+    if (fcntl(whc->si.fd, F_SETFL, O_NONBLOCK) >= 0) {
+      while ((read(whc->si.fd, &ch, 1) > 0) && (drain_bytes < MAX_DRAIN_BYTES)) {
+        drain_bytes++;
+      }
+    }
+#endif
+    close_socket(whc->si.fd);
+  }
+  // clean up ssl
+  if (whc->server_state & WEB_HTTP_SERVER_STATE_SSL_ENABLED)
+    ssl_free(whc);
+
+  // clean up memory
+  WebHttpContextDestroy(whc);
+
+  return;
+
+}
+
+//-------------------------------------------------------------------------
 // WebHttpSetErrorResponse
 //
 // Formulates a page to return on an HttpStatus condition

Copied: trafficserver/traffic/trunk/proxy/mgmt/web2/WebHttp.h (from r1059429, trafficserver/traffic/trunk/proxy/mgmt/web2/WebHttp.h)
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/mgmt/web2/WebHttp.h?p2=trafficserver/traffic/trunk/proxy/mgmt/web2/WebHttp.h&p1=trafficserver/traffic/trunk/proxy/mgmt/web2/WebHttp.h&r1=1059429&r2=1059969&rev=1059969&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/mgmt/web2/WebHttp.h (original)
+++ trafficserver/traffic/trunk/proxy/mgmt/web2/WebHttp.h Mon Jan 17 16:11:27 2011
@@ -38,6 +38,7 @@
 #include "P_RecCore.h"
 
 void WebHttpInit();
+void WebHttpHandleConnection(WebHttpConInfo * whci);
 
 void WebHttpSetErrorResponse(WebHttpContext * whc, HttpStatus_t error);
 char *WebHttpAddDocRoot_Xmalloc(WebHttpContext * whc, const char *file);



Mime
View raw message