/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */



#include "ngx_gzip_setter.h"

#include <ngx_conf_file.h>

namespace net_instaweb {

NgxGZipSetter g_gzip_setter;

extern "C" {
  // These functions replace the setters for:
  //   gzip
  //   gzip_types
  //   gzip_http_version
  //   gzip_vary
  //
  // If these functions are called it means there is an explicit gzip
  // configuration. The gzip configuration set by pagespeed is then rolled
  // back and pagespeed will stop enabling gzip automatically.
  char* ngx_gzip_redirect_conf_set_flag_slot(
      ngx_conf_t* cf, ngx_command_t* cmd, void* conf) {
    if (g_gzip_setter.enabled()) {
      g_gzip_setter.RollBackAndDisable(cf);
    }
    char* ret = ngx_conf_set_flag_slot(cf, cmd, conf);
    return ret;
  }

  char* ngx_gzip_redirect_http_types_slot(
      ngx_conf_t* cf, ngx_command_t* cmd, void* conf) {
    if (g_gzip_setter.enabled()) {
      g_gzip_setter.RollBackAndDisable(cf);
    }
    char* ret = ngx_http_types_slot(cf, cmd, conf);
    return ret;
  }

  char* ngx_gzip_redirect_conf_set_enum_slot(
      ngx_conf_t* cf, ngx_command_t* cmd, void* conf) {
    if (g_gzip_setter.enabled()) {
      g_gzip_setter.RollBackAndDisable(cf);
    }
    char* ret = ngx_conf_set_enum_slot(cf, cmd, conf);
    return ret;
  }
  char* ngx_gzip_redirect_conf_set_bitmask_slot(
      ngx_conf_t* cf, ngx_command_t* cmd, void* conf) {
    if (g_gzip_setter.enabled()) {
      g_gzip_setter.RollBackAndDisable(cf);
    }
    char* ret = ngx_conf_set_bitmask_slot(cf, cmd, conf);
    return ret;
  }
}

NgxGZipSetter::NgxGZipSetter() : enabled_(0) { }
NgxGZipSetter::~NgxGZipSetter() { }

// Helper functions to determine signature.
bool HasLocalConfig(ngx_command_t* command) {
  return (!(command->type & (NGX_DIRECT_CONF|NGX_MAIN_CONF)) &&
          command->conf == NGX_HTTP_LOC_CONF_OFFSET);
}
bool IsNgxFlagCommand(ngx_command_t* command) {
  return (command->set == ngx_conf_set_flag_slot &&
          HasLocalConfig(command));
}
bool IsNgxHttpTypesCommand(ngx_command_t* command) {
  return (command->set == ngx_http_types_slot &&
          HasLocalConfig(command));
}
bool IsNgxEnumCommand(ngx_command_t* command) {
  return (command->set == ngx_conf_set_enum_slot &&
          HasLocalConfig(command));
}
bool IsNgxBitmaskCommand(ngx_command_t* command) {
  return (command->set == ngx_conf_set_bitmask_slot &&
          HasLocalConfig(command));
}

// Initialize the NgxGzipSetter.
// Find the gzip, gzip_vary, gzip_http_version and gzip_types commands in the
// gzip module. Enable if the signature of the zip command matches with what we
// trust. Also sets up redirects for the configurations. These redirect handle
// a rollback if expicit configuration is found.
// If commands are not found the method will inform the user by logging.
void NgxGZipSetter::Init(ngx_conf_t* cf) {
#if (NGX_HTTP_GZIP)
  bool gzip_signature_mismatch = false;
  bool other_signature_mismatch = false;
  for (int m = 0; cf->cycle->modules[m] != NULL; m++) {
    if (cf->cycle->modules[m]->commands != NULL) {
      for (int c = 0; cf->cycle->modules[m]->commands[c].name.len; c++) {
        ngx_command_t* current_command =& cf->cycle->modules[m]->commands[c];

        // We look for the gzip command, and the exact signature we trust
        // this means configured as an config location offset
        // and a ngx_flag_t setter.
        // Also see:
        //   ngx_conf_handler in ngx_conf_file.c
        //   ngx_http_gzip_filter_commands in ngx_http_gzip_filter.c
        if (gzip_command_.command_ == NULL &&
            STR_EQ_LITERAL(current_command->name, "gzip")) {
          if (IsNgxFlagCommand(current_command)) {
            current_command->set = ngx_gzip_redirect_conf_set_flag_slot;
            gzip_command_.command_ = current_command;
            gzip_command_.module_ = cf->cycle->modules[m];
            enabled_ = 1;
          } else {
            ngx_conf_log_error(
                NGX_LOG_WARN, cf, 0,
                "pagespeed: cannot set gzip, signature mismatch");
            gzip_signature_mismatch = true;
          }
        }

        if (!gzip_http_version_command_.command_ &&
            STR_EQ_LITERAL(current_command->name, "gzip_http_version")) {
          if (IsNgxEnumCommand(current_command)) {
            current_command->set = ngx_gzip_redirect_conf_set_enum_slot;
            gzip_http_version_command_.command_ = current_command;
            gzip_http_version_command_.module_ = cf->cycle->modules[m];
          } else {
            ngx_conf_log_error(
                NGX_LOG_WARN, cf, 0,
                "pagespeed: cannot set gzip_http_version, signature mismatch");
            other_signature_mismatch = true;
          }
        }

        if (!gzip_proxied_command_.command_ &&
            STR_EQ_LITERAL(current_command->name, "gzip_proxied")) {
          if (IsNgxBitmaskCommand(current_command)) {
            current_command->set = ngx_gzip_redirect_conf_set_bitmask_slot;
            gzip_proxied_command_.command_ = current_command;
            gzip_proxied_command_.module_ = cf->cycle->modules[m];
          } else {
            ngx_conf_log_error(
                NGX_LOG_WARN, cf, 0,
                "pagespeed: cannot set gzip_proxied, signature mismatch");
            other_signature_mismatch = true;
          }
        }

        if (!gzip_http_types_command_.command_ &&
            STR_EQ_LITERAL(current_command->name, "gzip_types")) {
          if (IsNgxHttpTypesCommand(current_command)) {
            current_command->set = ngx_gzip_redirect_http_types_slot;
            gzip_http_types_command_.command_ = current_command;
            gzip_http_types_command_.module_ = cf->cycle->modules[m];
          } else {
            ngx_conf_log_error(
                NGX_LOG_WARN, cf, 0,
                "pagespeed: cannot set gzip_types, signature mismatch");
            other_signature_mismatch = true;
          }
        }

        if (!gzip_vary_command_.command_ &&
            STR_EQ_LITERAL(current_command->name, "gzip_vary")) {
          if (IsNgxFlagCommand(current_command)) {
            current_command->set = ngx_gzip_redirect_conf_set_flag_slot;
            gzip_vary_command_.command_ = current_command;
            gzip_vary_command_.module_ = cf->cycle->modules[m];
          } else {
            ngx_conf_log_error(
                NGX_LOG_WARN, cf, 0,
                "pagespeed: cannot set gzip_vary, signature mismatch");
            other_signature_mismatch = true;
          }
        }
      }
    }
  }
  if (gzip_signature_mismatch) {
    return;  // Already logged error.
  } else if (!enabled_) {
    // Looked through all the available commands and didn't find the "gzip" one.
    ngx_conf_log_error(
        NGX_LOG_WARN, cf, 0, "pagespeed: cannot set gzip, command not found");
    return;
  } else if (other_signature_mismatch) {
    return;  // Already logged error.
  } else if (!gzip_vary_command_.command_) {
    ngx_conf_log_error(
        NGX_LOG_WARN, cf, 0, "pagespeed: missing gzip_vary");
    return;
  } else if (!gzip_http_types_command_.command_) {
    ngx_conf_log_error(
        NGX_LOG_WARN, cf, 0, "pagespeed: missing gzip_types");
    return;
  } else if (!gzip_http_version_command_.command_) {
    ngx_conf_log_error(
        NGX_LOG_WARN, cf, 0, "pagespeed: missing gzip_http_version");
    return;
  } else if (!gzip_proxied_command_.command_) {
    ngx_conf_log_error(
        NGX_LOG_WARN, cf, 0, "pagespeed: missing gzip_proxied");
    return;
  } else {
    return;  // Success.
  }
#else
  ngx_conf_log_error(
      NGX_LOG_WARN, cf, 0, "pagespeed: gzip not compiled into nginx");
  return;
#endif
}

void* ngx_command_ctx::GetConfPtr(ngx_conf_t* cf) {
  return GetModuleConfPtr(cf) + command_->offset;
}

char* ngx_command_ctx::GetModuleConfPtr(ngx_conf_t* cf) {
  return reinterpret_cast<char*>(
      ngx_http_conf_get_module_loc_conf(cf, (*(module_))));
}

void NgxGZipSetter::SetNgxConfFlag(ngx_conf_t* cf,
                                   ngx_command_ctx* command_ctx,
                                   ngx_flag_t value) {
  ngx_flag_t* flag = reinterpret_cast<ngx_flag_t*>(command_ctx->GetConfPtr(cf));
  *flag = value;
  // Save the flag position for possible rollback.
  ngx_flags_set_.push_back(flag);
}

void NgxGZipSetter::SetNgxConfEnum(ngx_conf_t* cf,
                                   ngx_command_ctx* command_ctx,
                                   ngx_uint_t value) {
  ngx_uint_t* enum_to_set =
      reinterpret_cast<ngx_uint_t*>(command_ctx->GetConfPtr(cf));
  *enum_to_set = value;
  ngx_uint_set_.push_back(enum_to_set);
}

void NgxGZipSetter::SetNgxConfBitmask(ngx_conf_t* cf,
                                      ngx_command_ctx* command_ctx,
                                      ngx_uint_t value) {
  ngx_uint_t* enum_to_set =
      reinterpret_cast<ngx_uint_t*>(command_ctx->GetConfPtr(cf));
  *enum_to_set = value;
  ngx_uint_set_.push_back(enum_to_set);
}

// These are the content types we want to compress.
ngx_str_t gzip_http_types[] = {
  ngx_string("application/ecmascript"),
  ngx_string("application/javascript"),
  ngx_string("application/json"),
  ngx_string("application/pdf"),
  ngx_string("application/postscript"),
  ngx_string("application/x-javascript"),
  ngx_string("image/svg+xml"),
  ngx_string("text/css"),
  ngx_string("text/csv"),
  // ngx_string("text/html"),  // This is the default implied value.
  ngx_string("text/javascript"),
  ngx_string("text/plain"),
  ngx_string("text/xml"),
  ngx_null_string  // Indicates end of array.
};

gzs_enable_result NgxGZipSetter::SetGZipForLocation(ngx_conf_t* cf,
                                                    bool value) {
  if (!enabled_) {
    return kEnableGZipNotEnabled;
  }
  if (gzip_command_.command_) {
    SetNgxConfFlag(cf, &gzip_command_, value);
  }
  return kEnableGZipOk;
}

void NgxGZipSetter::EnableGZipForLocation(ngx_conf_t* cf) {
  if (!enabled_) {
    return;
  }

  // When we get called twice for the same location{}, we ignore the second call
  // to prevent adding duplicate gzip http types and so on.
  ngx_flag_t* flag =
      reinterpret_cast<ngx_flag_t*>(gzip_command_.GetConfPtr(cf));
  if (*flag == 1) {
    return;
  }
  SetGZipForLocation(cf, true);
  if (gzip_vary_command_.command_) {
    SetNgxConfFlag(cf, &gzip_vary_command_, 1);
  }
  if (gzip_http_version_command_.command_) {
    SetNgxConfEnum(cf, &gzip_http_version_command_, NGX_HTTP_VERSION_10);
  }
  if (gzip_proxied_command_.command_) {
    SetNgxConfBitmask(
        cf, &gzip_proxied_command_, NGX_HTTP_GZIP_PROXIED_ANY);
  }

  // This is actually the most prone to future API changes, because gzip_types
  // is not a simple type like ngx_flag_t. The signature check should be enough
  // to prevent problems.
  AddGZipHTTPTypes(cf);
  return;
}

void NgxGZipSetter::AddGZipHTTPTypes(ngx_conf_t* cf) {
  if (gzip_http_types_command_.command_) {
    // Following should not happen, but if it does return gracefully.
    if (cf->args->nalloc < 2) {
      ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                         "pagespeed: unexpected small cf->args in gzip_types");
      return;
    }

    ngx_command_t* command = gzip_http_types_command_.command_;
    char* gzip_conf = reinterpret_cast<char* >(
        gzip_http_types_command_.GetModuleConfPtr(cf));

    // Backup the old settings.
    ngx_str_t old_elt0 = reinterpret_cast<ngx_str_t*>(cf->args->elts)[0];
    ngx_str_t old_elt1 = reinterpret_cast<ngx_str_t*>(cf->args->elts)[1];
    ngx_uint_t old_nelts = cf->args->nelts;

    // Setup first arg.
    ngx_str_t gzip_types_string = ngx_string("gzip_types");
    reinterpret_cast<ngx_str_t*>(cf->args->elts)[0] = gzip_types_string;
    cf->args->nelts = 2;

    ngx_str_t* http_types = gzip_http_types;
    while (http_types->data) {
      ngx_str_t d;
      // We allocate the http type on the configuration pool and actually
      // leak this if we rollback. This does not seem to be a big problem,
      // because nginx also allocates tokens in ngx_conf_file.c and does not
      // free them. This way they can be used safely by configurations.
      // We must use a copy of gzip_http_types array here because nginx will
      // manipulate the values.
      // TODO(kspoelstra): better would be to allocate once on init and not
      // every time we enable gzip. This needs further investigation, sharing
      // tokens might be problematic.
      // For now I think it is not a large problem. This might add up in case
      // of a large multi server/location config with a lot of "pagespeed on"
      // directives.
      // Estimates are 300-400KB for 1000 times "pagespeed on".
      d.data = reinterpret_cast<u_char*>(
          ngx_pnalloc(cf->pool, http_types->len + 1));
      snprintf(reinterpret_cast<char*>(d.data), http_types->len + 1, "%s",
               reinterpret_cast<const char*>(http_types->data));
      d.len = http_types->len;
      reinterpret_cast<ngx_str_t*>(cf->args->elts)[1] = d;
      // Call the original setter.
      ngx_http_types_slot(cf, command, gzip_conf);
      http_types++;
    }

    // Restore args.
    cf->args->nelts = old_nelts;
    reinterpret_cast<ngx_str_t*>(cf->args->elts)[1] = old_elt1;
    reinterpret_cast<ngx_str_t*>(cf->args->elts)[0] = old_elt0;

    // Backup configuration location for rollback.
    ngx_httptypes_set_.push_back(gzip_conf + command->offset);
  }
}

void NgxGZipSetter::RollBackAndDisable(ngx_conf_t* cf) {
  ngx_conf_log_error(NGX_LOG_INFO, cf, 0,
                     "pagespeed: rollback gzip, explicit configuration");
  for (std::vector<ngx_flag_t*>::iterator i = ngx_flags_set_.begin();
       i != ngx_flags_set_.end(); ++i) {
    *(*i)=NGX_CONF_UNSET;
  }
  for (std::vector<ngx_uint_t*>::iterator i = ngx_uint_set_.begin();
       i != ngx_uint_set_.end(); ++i) {
    *(*i)=NGX_CONF_UNSET_UINT;
  }
  for (std::vector<void*>::iterator i = ngx_httptypes_set_.begin();
       i != ngx_httptypes_set_.end(); ++i) {
    ngx_array_t** type_array = reinterpret_cast<ngx_array_t**>(*i);
    ngx_array_destroy(*type_array);
    *type_array = NULL;
  }
  enabled_ = 0;
}

}  // namespace net_instaweb
