<commit_before>#include "PipeBase.h"
#include "Simulation.h"
#include "FEProblem.h"
#include "Conversion.h"
#include "R7Conversion.h"
#include "Factory.h"

#include "edge_edge2.h"
#include "fe_type.h"

const std::string PipeBase::_type("pipe");

template<>
InputParameters validParams<PipeBase>()
{
  InputParameters params = validParams<Component>();
  //Input parameters [NO] default values should be given.
  params.addRequiredParam<std::vector<Real> >("position", "Origin (start) of the pipe");

  std::vector<Real> zr(LIBMESH_DIM, 0.);
  params.addParam<std::vector<Real> >("offset", zr, "Offset of the origin for mesh generation");
  params.addRequiredParam<std::vector<Real> >("orientation", "Orientation vector of the pipe");
  params.addRequiredParam<Real>("length", "Length of the pipe");
  params.addRequiredParam<unsigned int>("n_elems", "number of element in this pipe");
  params.addRequiredParam<Real>("A", "Area of the pipe");
  params.addRequiredParam<UserObjectName>("eos", "The name of EOS to use");

  //Input parameters default values could be given.
  params.addParam<Real>("f", 0.0, "friction");
  params.addParam<Real>("Hw", 0.0, "Convective heat transfer coefficient");
  params.addParam<Real>("Tw", 400, "Wall temperature");

  params.addParam<Real>("initial_P", 0., "Initial pressure in the pipe");
  params.addParam<Real>("initial_V", 0., "Initial velocity in the pipe");
  params.addParam<Real>("initial_T", 300., "Initial temperature in the pipe");

  return params;
}

PipeBase::PipeBase(const std::string & name, InputParameters params) :
    Component(name, params),
    Model(params),
    _position(toPoint(getParam<std::vector<Real> >("position"))),
    _offset(toPoint(getParam<std::vector<Real> >("offset"))),
    _length(getParam<Real>("length")),
    _n_elems(getParam<unsigned int>("n_elems")),
    _A(getParam<Real>("A")),
    _has_f(params.wasSeenInInput("f")),
    _f(getParam<Real>("f")),
    _Hw(getParam<Real>("Hw")),
    _Tw(getParam<Real>("Tw")),
    _has_initial_P(params.wasSeenInInput("initial_P")),
    _has_initial_V(params.wasSeenInInput("initial_V")),
    _has_initial_T(params.wasSeenInInput("initial_T")),
    _initial_P(_has_initial_P ? getParam<Real>("initial_P") : 0.),
    _initial_V(_has_initial_V ? getParam<Real>("initial_V") : 0.),
    _initial_T(_has_initial_T ? getParam<Real>("initial_T") : 300.)
{
  const std::vector<Real> & dir = getParam<std::vector<Real> >("orientation");
  _dir = VectorValue<Real>(dir[0], dir[1], dir[2]);

  //compute the gravity along the pipe direction.
  RealVectorValue gravity_vector = _sim.getParam<VectorValue<Real> >("gravity");
  _gx = _dir * gravity_vector / _dir.size();
}

PipeBase::~PipeBase()
{
}

Node *
PipeBase::getBoundaryNode(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, Node *>::iterator it = _bnd_nodes.find(id);
  if (it != _bnd_nodes.end())
    return it->second;
  else
    return NULL;
}

unsigned int
PipeBase::getBoundaryId(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, unsigned int>::iterator it = _bnd_ids.find(id);
  if (it != _bnd_ids.end())
    return it->second;
  else
    mooseError("PipeBase " << name() << " does not have this type of end defined.");
}

int
PipeBase::getBoundaryOutNorm(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, int>::iterator it = _bnd_out_norm.find(id);
  if (it != _bnd_out_norm.end())
    return it->second;
  else
    mooseError("PipeBase " << name() << " does not have this type of end defined.");
}

void
PipeBase::buildMesh()
{
  // points
  Real delta_t = _length / _n_elems;
  Point p(0, 0, 0);                      // origin
  p += _offset;
  for (unsigned int i = 0; i <= _n_elems; i++)
  {
    const Node * nd = _mesh._mesh.add_point(p);
    node_ids.push_back(nd->id());
    p(0) += delta_t;
  }

  // elems
  _subdomain_id = getNextSubdomainId();
  unsigned int bc_id_in = getNextBCId();
  unsigned int bc_id_out = getNextBCId();
  for (unsigned int i = 0; i < _n_elems; i++)
  {
    Elem * elem = _mesh._mesh.add_elem (new Edge2);
    elem->subdomain_id() = _subdomain_id;
    elem->set_node(0) = _mesh._mesh.node_ptr(node_ids[i]);
    elem->set_node(1) = _mesh._mesh.node_ptr(node_ids[i+1]);
    elem_ids.push_back(elem->id());

    // BCs
    if (i == 0)
    {
      _bnd_ids[RELAP7::IN] = bc_id_in;
      _mesh._mesh.boundary_info->add_side(elem, 0, bc_id_in);
      _bnd_nodes[RELAP7::IN] = elem->get_node(0);                // first 0 is local bnd_id that Joints will use for connecting
      _bnd_out_norm[RELAP7::IN] = -1;
    }
    if (i == (_n_elems - 1))
    {
      _bnd_ids[RELAP7::OUT] = bc_id_out;
      _mesh._mesh.boundary_info->add_side(elem, 1, bc_id_out);
      _bnd_nodes[RELAP7::OUT] = elem->get_node(1);               // first 1 is local bnd_id that Joints will use for connecting
      _bnd_out_norm[RELAP7::OUT] = 1;
    }
 }
}

void
PipeBase::addVariables()
{
  Model::addVariables(_subdomain_id);

  const EquationOfState & eos = _sim.getEquationOfState(getParam<UserObjectName>("eos"));

  Real initial_P = _sim.getParam<Real>("global_init_P");
  Real initial_V = _sim.getParam<Real>("global_init_V");
  Real initial_T = _sim.getParam<Real>("global_init_T");
  if(_has_initial_P)
	  initial_P = _initial_P;			//replace by local initial conditions
  if(_has_initial_V)
	  initial_V = _initial_V;
  if(_has_initial_T)
	  initial_T = _initial_T;

  //Model::addInitialConditions(_subdomain_id, initial_P, initial_V, initial_T);

  Real initial_rho = 0.;
  Real initial_rhou = 0.;
  Real initial_e = 0.;
  Real initial_rhoE = 0.;
  Real initial_enthalpy = 0.;
  if(_model_type == EQ_MODEL_2)
  {
	  initial_rho = eos.invert_eos_rho(initial_P);
	  initial_rhou = initial_rho * initial_V;
  }
  else if(_model_type == EQ_MODEL_3)
  {
	  initial_e = eos.invert_eos_internal_energy(initial_T);
	  initial_rho = eos.invert_eos_rho(initial_P, initial_e);
	  initial_rhou = initial_rho * initial_V;
	  initial_rhoE = initial_rho * initial_e + initial_rho * 0.5 * initial_V * initial_V;
	  initial_enthalpy = (initial_rhoE + initial_P) / initial_rho;
  }
  else
	  mooseError("wrong model type");

  Model::addInitialConditions(_subdomain_id, initial_P, initial_V, initial_rho, initial_rhou, initial_T, initial_rhoE, initial_enthalpy);
}

void
PipeBase::addMooseObjects()
{
  std::vector<unsigned int> blocks(1, _subdomain_id);

  InputParameters pars = emptyInputParameters();
  pars.set<std::vector<unsigned int> >("block") = blocks;

  pars.set<Real>("gx") = _gx;
  pars.set<Real>("dh") = _Dh;
  pars.set<Real>("aw") = _aw;
  if (_has_f)
    pars.set<Real>("f") = _f;
  pars.set<Real>("Hw") = _Hw;
  pars.set<Real>("Tw") = _Tw;
  pars.set<UserObjectName>("eos") = getParam<UserObjectName>("eos");

  Model::addKernels(pars);

  if (_model_type == EQ_MODEL_3)
  {
    // for 3 eqn model, add wall heating term

    std::vector<std::string> cv_rho(1, RHO);
    std::vector<std::string> cv_temperature(1, TEMPERATURE);

    InputParameters params = Factory::instance()->getValidParams("OneDEnergyWallHeating");
    params.set<NonlinearVariableName>("variable") = Model::RHOE;
    params.set<std::vector<unsigned int> >("block") = blocks;

    params.set<Real>("Hw") = _Hw;
    params.set<Real>("aw") = _aw;
    params.set<Real>("Tw") = _Tw;

    params.set<std::vector<std::string> >("rho") = cv_rho;
    params.set<std::vector<std::string> >("temperature") = cv_temperature;

    std::string mon = genName(name(), _id, "_pipe");
    _sim.addKernel("OneDEnergyWallHeating", mon, params);
    connectObject("", mon);
  }
}

std::vector<unsigned int>
PipeBase::getIDs(std::string part)
{
  std::vector<unsigned int> ids;

  if(part == "PIPE")
    ids.push_back(_subdomain_id);
  else
    mooseError(part + " is not a valid part of PipeBase!");

  return ids;
}

std::string
PipeBase::variableName(std::string part)
{
  if(part == "FLUID_TEMP")
    return Model::TEMPERATURE;
  else
    mooseError(part + " is not a valid part of PipeBase!");
}
<commit_msg>Adding component type into validParams() (closes #1242)<commit_after>#include "PipeBase.h"
#include "Simulation.h"
#include "FEProblem.h"
#include "Conversion.h"
#include "R7Conversion.h"
#include "Factory.h"

#include "edge_edge2.h"
#include "fe_type.h"

const std::string PipeBase::_type("pipe");

template<>
InputParameters validParams<PipeBase>()
{
  InputParameters params = validParams<Component>();
  params.addParam("component_type", PipeBase::_type, "The type of the component");
  //Input parameters [NO] default values should be given.
  params.addRequiredParam<std::vector<Real> >("position", "Origin (start) of the pipe");

  std::vector<Real> zr(LIBMESH_DIM, 0.);
  params.addParam<std::vector<Real> >("offset", zr, "Offset of the origin for mesh generation");
  params.addRequiredParam<std::vector<Real> >("orientation", "Orientation vector of the pipe");
  params.addRequiredParam<Real>("length", "Length of the pipe");
  params.addRequiredParam<unsigned int>("n_elems", "number of element in this pipe");
  params.addRequiredParam<Real>("A", "Area of the pipe");
  params.addRequiredParam<UserObjectName>("eos", "The name of EOS to use");

  //Input parameters default values could be given.
  params.addParam<Real>("f", 0.0, "friction");
  params.addParam<Real>("Hw", 0.0, "Convective heat transfer coefficient");
  params.addParam<Real>("Tw", 400, "Wall temperature");

  params.addParam<Real>("initial_P", 0., "Initial pressure in the pipe");
  params.addParam<Real>("initial_V", 0., "Initial velocity in the pipe");
  params.addParam<Real>("initial_T", 300., "Initial temperature in the pipe");

  return params;
}

PipeBase::PipeBase(const std::string & name, InputParameters params) :
    Component(name, params),
    Model(params),
    _position(toPoint(getParam<std::vector<Real> >("position"))),
    _offset(toPoint(getParam<std::vector<Real> >("offset"))),
    _length(getParam<Real>("length")),
    _n_elems(getParam<unsigned int>("n_elems")),
    _A(getParam<Real>("A")),
    _has_f(params.wasSeenInInput("f")),
    _f(getParam<Real>("f")),
    _Hw(getParam<Real>("Hw")),
    _Tw(getParam<Real>("Tw")),
    _has_initial_P(params.wasSeenInInput("initial_P")),
    _has_initial_V(params.wasSeenInInput("initial_V")),
    _has_initial_T(params.wasSeenInInput("initial_T")),
    _initial_P(_has_initial_P ? getParam<Real>("initial_P") : 0.),
    _initial_V(_has_initial_V ? getParam<Real>("initial_V") : 0.),
    _initial_T(_has_initial_T ? getParam<Real>("initial_T") : 300.)
{
  const std::vector<Real> & dir = getParam<std::vector<Real> >("orientation");
  _dir = VectorValue<Real>(dir[0], dir[1], dir[2]);

  //compute the gravity along the pipe direction.
  RealVectorValue gravity_vector = _sim.getParam<VectorValue<Real> >("gravity");
  _gx = _dir * gravity_vector / _dir.size();
}

PipeBase::~PipeBase()
{
}

Node *
PipeBase::getBoundaryNode(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, Node *>::iterator it = _bnd_nodes.find(id);
  if (it != _bnd_nodes.end())
    return it->second;
  else
    return NULL;
}

unsigned int
PipeBase::getBoundaryId(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, unsigned int>::iterator it = _bnd_ids.find(id);
  if (it != _bnd_ids.end())
    return it->second;
  else
    mooseError("PipeBase " << name() << " does not have this type of end defined.");
}

int
PipeBase::getBoundaryOutNorm(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, int>::iterator it = _bnd_out_norm.find(id);
  if (it != _bnd_out_norm.end())
    return it->second;
  else
    mooseError("PipeBase " << name() << " does not have this type of end defined.");
}

void
PipeBase::buildMesh()
{
  // points
  Real delta_t = _length / _n_elems;
  Point p(0, 0, 0);                      // origin
  p += _offset;
  for (unsigned int i = 0; i <= _n_elems; i++)
  {
    const Node * nd = _mesh._mesh.add_point(p);
    node_ids.push_back(nd->id());
    p(0) += delta_t;
  }

  // elems
  _subdomain_id = getNextSubdomainId();
  unsigned int bc_id_in = getNextBCId();
  unsigned int bc_id_out = getNextBCId();
  for (unsigned int i = 0; i < _n_elems; i++)
  {
    Elem * elem = _mesh._mesh.add_elem (new Edge2);
    elem->subdomain_id() = _subdomain_id;
    elem->set_node(0) = _mesh._mesh.node_ptr(node_ids[i]);
    elem->set_node(1) = _mesh._mesh.node_ptr(node_ids[i+1]);
    elem_ids.push_back(elem->id());

    // BCs
    if (i == 0)
    {
      _bnd_ids[RELAP7::IN] = bc_id_in;
      _mesh._mesh.boundary_info->add_side(elem, 0, bc_id_in);
      _bnd_nodes[RELAP7::IN] = elem->get_node(0);                // first 0 is local bnd_id that Joints will use for connecting
      _bnd_out_norm[RELAP7::IN] = -1;
    }
    if (i == (_n_elems - 1))
    {
      _bnd_ids[RELAP7::OUT] = bc_id_out;
      _mesh._mesh.boundary_info->add_side(elem, 1, bc_id_out);
      _bnd_nodes[RELAP7::OUT] = elem->get_node(1);               // first 1 is local bnd_id that Joints will use for connecting
      _bnd_out_norm[RELAP7::OUT] = 1;
    }
 }
}

void
PipeBase::addVariables()
{
  Model::addVariables(_subdomain_id);

  const EquationOfState & eos = _sim.getEquationOfState(getParam<UserObjectName>("eos"));

  Real initial_P = _sim.getParam<Real>("global_init_P");
  Real initial_V = _sim.getParam<Real>("global_init_V");
  Real initial_T = _sim.getParam<Real>("global_init_T");
  if(_has_initial_P)
	  initial_P = _initial_P;			//replace by local initial conditions
  if(_has_initial_V)
	  initial_V = _initial_V;
  if(_has_initial_T)
	  initial_T = _initial_T;

  //Model::addInitialConditions(_subdomain_id, initial_P, initial_V, initial_T);

  Real initial_rho = 0.;
  Real initial_rhou = 0.;
  Real initial_e = 0.;
  Real initial_rhoE = 0.;
  Real initial_enthalpy = 0.;
  if(_model_type == EQ_MODEL_2)
  {
	  initial_rho = eos.invert_eos_rho(initial_P);
	  initial_rhou = initial_rho * initial_V;
  }
  else if(_model_type == EQ_MODEL_3)
  {
	  initial_e = eos.invert_eos_internal_energy(initial_T);
	  initial_rho = eos.invert_eos_rho(initial_P, initial_e);
	  initial_rhou = initial_rho * initial_V;
	  initial_rhoE = initial_rho * initial_e + initial_rho * 0.5 * initial_V * initial_V;
	  initial_enthalpy = (initial_rhoE + initial_P) / initial_rho;
  }
  else
	  mooseError("wrong model type");

  Model::addInitialConditions(_subdomain_id, initial_P, initial_V, initial_rho, initial_rhou, initial_T, initial_rhoE, initial_enthalpy);
}

void
PipeBase::addMooseObjects()
{
  std::vector<unsigned int> blocks(1, _subdomain_id);

  InputParameters pars = emptyInputParameters();
  pars.set<std::vector<unsigned int> >("block") = blocks;

  pars.set<Real>("gx") = _gx;
  pars.set<Real>("dh") = _Dh;
  pars.set<Real>("aw") = _aw;
  if (_has_f)
    pars.set<Real>("f") = _f;
  pars.set<Real>("Hw") = _Hw;
  pars.set<Real>("Tw") = _Tw;
  pars.set<UserObjectName>("eos") = getParam<UserObjectName>("eos");

  Model::addKernels(pars);

  if (_model_type == EQ_MODEL_3)
  {
    // for 3 eqn model, add wall heating term

    std::vector<std::string> cv_rho(1, RHO);
    std::vector<std::string> cv_temperature(1, TEMPERATURE);

    InputParameters params = Factory::instance()->getValidParams("OneDEnergyWallHeating");
    params.set<NonlinearVariableName>("variable") = Model::RHOE;
    params.set<std::vector<unsigned int> >("block") = blocks;

    params.set<Real>("Hw") = _Hw;
    params.set<Real>("aw") = _aw;
    params.set<Real>("Tw") = _Tw;

    params.set<std::vector<std::string> >("rho") = cv_rho;
    params.set<std::vector<std::string> >("temperature") = cv_temperature;

    std::string mon = genName(name(), _id, "_pipe");
    _sim.addKernel("OneDEnergyWallHeating", mon, params);
    connectObject("", mon);
  }
}

std::vector<unsigned int>
PipeBase::getIDs(std::string part)
{
  std::vector<unsigned int> ids;

  if(part == "PIPE")
    ids.push_back(_subdomain_id);
  else
    mooseError(part + " is not a valid part of PipeBase!");

  return ids;
}

std::string
PipeBase::variableName(std::string part)
{
  if(part == "FLUID_TEMP")
    return Model::TEMPERATURE;
  else
    mooseError(part + " is not a valid part of PipeBase!");
}
<|endoftext|>


<commit_before>#include "PipeBase.h"
#include "Simulation.h"
#include "FEProblem.h"
#include "Conversion.h"
#include "R7Conversion.h"
#include "Factory.h"
// libMesh
#include "edge_edge2.h"
#include "fe_type.h"

const std::string PipeBase::_type("pipe");

template<>
InputParameters validParams<PipeBase>()
{
  InputParameters params = validParams<Component>();
  params.addParam("component_type", PipeBase::_type, "The type of the component");
  //Input parameters [NO] default values should be given.
  params.addRequiredParam<std::vector<Real> >("position", "Origin (start) of the pipe");

  std::vector<Real> zr(LIBMESH_DIM, 0.);
  params.addParam<std::vector<Real> >("offset", zr, "Offset of the origin for mesh generation");
  params.addRequiredParam<std::vector<Real> >("orientation", "Orientation vector of the pipe");
  params.addRequiredParam<Real>("length", "Length of the pipe");
  params.addRequiredParam<unsigned int>("n_elems", "number of element in this pipe");
  params.addRequiredParam<Real>("A", "Area of the pipe");
  params.addRequiredParam<UserObjectName>("eos", "The name of EOS to use");

  //Input parameters default values could be given.
  params.addParam<Real>("roughness", 0.0, "roughness, [m]");
  params.addParam<Real>("f", 0.0, "friction");
  params.addParam<Real>("Hw", 0.0, "Convective heat transfer coefficient");
  params.addParam<Real>("Tw", 400, "Wall temperature");
  params.addParam<unsigned int>("HT_geometry_code", 0, "Heat transfer geometry code");
  params.addParam<Real>("PoD", 1, "pitch to diameter ratio for parellel bundle heat transfer");

  params.addParam<Real>("initial_P", 0., "Initial pressure in the pipe");
  params.addParam<Real>("initial_V", 0., "Initial velocity in the pipe");
  params.addParam<Real>("initial_T", 300., "Initial temperature in the pipe");

  return params;
}

PipeBase::PipeBase(const std::string & name, InputParameters params) :
    Component(name, params),
    Model(params),
    _position(toPoint(getParam<std::vector<Real> >("position"))),
    _offset(toPoint(getParam<std::vector<Real> >("offset"))),
    _length(getParam<Real>("length")),
    _n_elems(getParam<unsigned int>("n_elems")),
    _A(getParam<Real>("A")),
    _roughness(getParam<Real>("roughness")),
    _has_f(params.wasSeenInInput("f")),
    _f(getParam<Real>("f")),
    _has_Hw(params.wasSeenInInput("Hw")),
    _Hw(getParam<Real>("Hw")),
    _Tw(getParam<Real>("Tw")),
    _HT_geometry_code(getParam<unsigned int>("HT_geometry_code")),
    _PoD(getParam<Real>("PoD")),
    _has_PoD(params.wasSeenInInput("PoD")),
    _has_initial_P(params.wasSeenInInput("initial_P")),
    _has_initial_V(params.wasSeenInInput("initial_V")),
    _has_initial_T(params.wasSeenInInput("initial_T")),
    _initial_P(_has_initial_P ? getParam<Real>("initial_P") : 0.),
    _initial_V(_has_initial_V ? getParam<Real>("initial_V") : 0.),
    _initial_T(_has_initial_T ? getParam<Real>("initial_T") : 300.)
{
  const std::vector<Real> & dir = getParam<std::vector<Real> >("orientation");
  _dir = VectorValue<Real>(dir[0], dir[1], dir[2]);

  //compute the gravity along the pipe direction.
  RealVectorValue gravity_vector = _sim.getParam<VectorValue<Real> >("gravity");
  _gx = _dir * gravity_vector / _dir.size();
  _g = gravity_vector.size(); // Gravity constant
}

PipeBase::~PipeBase()
{
}

Node *
PipeBase::getBoundaryNode(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, Node *>::iterator it = _bnd_nodes.find(id);
  if (it != _bnd_nodes.end())
    return it->second;
  else
    return NULL;
}

unsigned int
PipeBase::getBoundaryId(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, unsigned int>::iterator it = _bnd_ids.find(id);
  if (it != _bnd_ids.end())
    return it->second;
  else
    mooseError("PipeBase " << name() << " does not have this type of end defined.");
}

int
PipeBase::getBoundaryOutNorm(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, int>::iterator it = _bnd_out_norm.find(id);
  if (it != _bnd_out_norm.end())
    return it->second;
  else
    mooseError("PipeBase " << name() << " does not have this type of end defined.");
}

void
PipeBase::buildMesh()
{
  // points
  Real delta_t = _length / _n_elems;
  Point p(0, 0, 0);                      // origin
  p += _offset;
  for (unsigned int i = 0; i <= _n_elems; i++)
  {
    const Node * nd = _mesh._mesh.add_point(p);
    node_ids.push_back(nd->id());
    p(0) += delta_t;
  }

  // elems
  _subdomain_id = getNextSubdomainId();
  unsigned int bc_id_in = getNextBCId();
  unsigned int bc_id_out = getNextBCId();
  for (unsigned int i = 0; i < _n_elems; i++)
  {
    Elem * elem = _mesh._mesh.add_elem (new Edge2);
    elem->subdomain_id() = _subdomain_id;
    elem->set_node(0) = _mesh._mesh.node_ptr(node_ids[i]);
    elem->set_node(1) = _mesh._mesh.node_ptr(node_ids[i+1]);
    elem_ids.push_back(elem->id());

    // BCs
    if (i == 0)
    {
      _bnd_ids[RELAP7::IN] = bc_id_in;
      _mesh._mesh.boundary_info->add_side(elem, 0, bc_id_in);
      _bnd_nodes[RELAP7::IN] = elem->get_node(0);                // first 0 is local bnd_id that Joints will use for connecting
      _bnd_out_norm[RELAP7::IN] = -1;
    }
    if (i == (_n_elems - 1))
    {
      _bnd_ids[RELAP7::OUT] = bc_id_out;
      _mesh._mesh.boundary_info->add_side(elem, 1, bc_id_out);
      _bnd_nodes[RELAP7::OUT] = elem->get_node(1);               // first 1 is local bnd_id that Joints will use for connecting
      _bnd_out_norm[RELAP7::OUT] = 1;
    }
 }
}

void
PipeBase::addVariables()
{
  Model::addVariables(_subdomain_id);

  const EquationOfState & eos = _sim.getEquationOfState(getParam<UserObjectName>("eos"));

  Real initial_P = _sim.getParam<Real>("global_init_P");
  Real initial_V = _sim.getParam<Real>("global_init_V");
  Real initial_T = _sim.getParam<Real>("global_init_T");
  if(_has_initial_P)
    initial_P = _initial_P;			//replace by local initial conditions
  if(_has_initial_V)
    initial_V = _initial_V;
  if(_has_initial_T)
   initial_T = _initial_T;

  Real initial_rho = 0.;
  Real initial_rhou = 0.;
  Real initial_e = 0.;
  Real initial_rhoE = 0.;
  Real initial_enthalpy = 0.;
  if(_model_type == EQ_MODEL_2)
  {
    initial_rho = eos.invert_eos_rho(initial_P);
    initial_rhou = initial_rho * initial_V;
  }
  else if(_model_type == EQ_MODEL_3)
  {
    initial_e = eos.invert_eos_internal_energy(initial_T);
    initial_rho = eos.invert_eos_rho(initial_P, initial_e);
    initial_rhou = initial_rho * initial_V;
    initial_rhoE = initial_rho * initial_e + initial_rho * 0.5 * initial_V * initial_V;
    initial_enthalpy = (initial_rhoE + initial_P) / initial_rho;
  }
  else
    mooseError("wrong model type");

  Model::addInitialConditions(_subdomain_id, initial_P, initial_V, initial_rho, initial_rhou, initial_T, initial_rhoE, initial_enthalpy);
}

void
PipeBase::addMooseObjects()
{
  std::vector<unsigned int> blocks(1, _subdomain_id);

  InputParameters pars = emptyInputParameters();
  pars.set<std::vector<unsigned int> >("block") = blocks;

  pars.set<Real>("gx") = _gx;
  pars.set<Real>("g") = _g; // gravity constant
  pars.set<Real>("dh") = _Dh;
  pars.set<Real>("roughness") = _roughness;
  pars.set<Real>("aw") = _aw;
  if (_has_f)
    pars.set<Real>("f") = _f;
  if(_has_Hw)
    pars.set<Real>("Hw") = _Hw;
  pars.set<Real>("Tw") = _Tw;
  pars.set<unsigned int>("HT_geometry_code") = _HT_geometry_code;
  if (_has_PoD)
    pars.set<Real>("PoD") = _PoD;
  pars.set<UserObjectName>("eos") = getParam<UserObjectName>("eos");

  Model::addKernels(pars);

  if (_model_type == EQ_MODEL_3)
  {
    // for 3 eqn model, add wall heating term

    std::vector<std::string> cv_rho(1, RHO);
    std::vector<std::string> cv_temperature(1, TEMPERATURE);

    InputParameters params = Factory::instance()->getValidParams("OneDEnergyWallHeating");
    params.set<NonlinearVariableName>("variable") = Model::RHOE;
    params.set<std::vector<unsigned int> >("block") = blocks;

    params.set<Real>("Hw") = _Hw;
    params.set<Real>("aw") = _aw;
    params.set<Real>("Tw") = _Tw;

    params.set<std::vector<std::string> >("rho") = cv_rho;
    params.set<std::vector<std::string> >("temperature") = cv_temperature;

    std::string mon = genName(name(), _id, "_pipe");
    _sim.addKernel("OneDEnergyWallHeating", mon, params);
    connectObject("", mon);
  }
}
<commit_msg>enable wall friction and heat transfer closure models in HeatExchanger component, add one new heat transfer test case for sodium to sodium heat exchanger<commit_after>#include "PipeBase.h"
#include "Simulation.h"
#include "FEProblem.h"
#include "Conversion.h"
#include "R7Conversion.h"
#include "Factory.h"
// libMesh
#include "edge_edge2.h"
#include "fe_type.h"

const std::string PipeBase::_type("pipe");

template<>
InputParameters validParams<PipeBase>()
{
  InputParameters params = validParams<Component>();
  params.addParam("component_type", PipeBase::_type, "The type of the component");
  //Input parameters [NO] default values should be given.
  params.addRequiredParam<std::vector<Real> >("position", "Origin (start) of the pipe");

  std::vector<Real> zr(LIBMESH_DIM, 0.);
  params.addParam<std::vector<Real> >("offset", zr, "Offset of the origin for mesh generation");
  params.addRequiredParam<std::vector<Real> >("orientation", "Orientation vector of the pipe");
  params.addRequiredParam<Real>("length", "Length of the pipe");
  params.addRequiredParam<unsigned int>("n_elems", "number of element in this pipe");
  params.addRequiredParam<Real>("A", "Area of the pipe");
  params.addRequiredParam<UserObjectName>("eos", "The name of EOS to use");

  //Input parameters default values could be given.
  params.addParam<Real>("roughness", 0.0, "roughness, [m]");
  params.addParam<Real>("f", 0.0, "friction");
  params.addParam<Real>("Hw", 0.0, "Convective heat transfer coefficient");
  params.addParam<Real>("Tw", 400, "Wall temperature");
  params.addParam<unsigned int>("HT_geometry_code", 0, "Heat transfer geometry code");
  params.addParam<Real>("PoD", 1, "pitch to diameter ratio for parellel bundle heat transfer");

  params.addParam<Real>("initial_P", 1e5, "Initial pressure in the pipe");
  params.addParam<Real>("initial_V", 0., "Initial velocity in the pipe");
  params.addParam<Real>("initial_T", 300., "Initial temperature in the pipe");

  return params;
}

PipeBase::PipeBase(const std::string & name, InputParameters params) :
    Component(name, params),
    Model(params),
    _position(toPoint(getParam<std::vector<Real> >("position"))),
    _offset(toPoint(getParam<std::vector<Real> >("offset"))),
    _length(getParam<Real>("length")),
    _n_elems(getParam<unsigned int>("n_elems")),
    _A(getParam<Real>("A")),
    _roughness(getParam<Real>("roughness")),
    _has_f(params.wasSeenInInput("f")),
    _f(getParam<Real>("f")),
    _has_Hw(params.wasSeenInInput("Hw")),
    _Hw(getParam<Real>("Hw")),
    _Tw(getParam<Real>("Tw")),
    _HT_geometry_code(getParam<unsigned int>("HT_geometry_code")),
    _PoD(getParam<Real>("PoD")),
    _has_PoD(params.wasSeenInInput("PoD")),
    _has_initial_P(params.wasSeenInInput("initial_P")),
    _has_initial_V(params.wasSeenInInput("initial_V")),
    _has_initial_T(params.wasSeenInInput("initial_T")),
    _initial_P(getParam<Real>("initial_P")),
    _initial_V(getParam<Real>("initial_V")),
    _initial_T(getParam<Real>("initial_T"))
{
  const std::vector<Real> & dir = getParam<std::vector<Real> >("orientation");
  _dir = VectorValue<Real>(dir[0], dir[1], dir[2]);

  //compute the gravity along the pipe direction.
  RealVectorValue gravity_vector = _sim.getParam<VectorValue<Real> >("gravity");
  _gx = _dir * gravity_vector / _dir.size();
  _g = gravity_vector.size(); // Gravity constant
}

PipeBase::~PipeBase()
{
}

Node *
PipeBase::getBoundaryNode(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, Node *>::iterator it = _bnd_nodes.find(id);
  if (it != _bnd_nodes.end())
    return it->second;
  else
    return NULL;
}

unsigned int
PipeBase::getBoundaryId(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, unsigned int>::iterator it = _bnd_ids.find(id);
  if (it != _bnd_ids.end())
    return it->second;
  else
    mooseError("PipeBase " << name() << " does not have this type of end defined.");
}

int
PipeBase::getBoundaryOutNorm(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, int>::iterator it = _bnd_out_norm.find(id);
  if (it != _bnd_out_norm.end())
    return it->second;
  else
    mooseError("PipeBase " << name() << " does not have this type of end defined.");
}

void
PipeBase::buildMesh()
{
  // points
  Real delta_t = _length / _n_elems;
  Point p(0, 0, 0);                      // origin
  p += _offset;
  for (unsigned int i = 0; i <= _n_elems; i++)
  {
    const Node * nd = _mesh._mesh.add_point(p);
    node_ids.push_back(nd->id());
    p(0) += delta_t;
  }

  // elems
  _subdomain_id = getNextSubdomainId();
  unsigned int bc_id_in = getNextBCId();
  unsigned int bc_id_out = getNextBCId();
  for (unsigned int i = 0; i < _n_elems; i++)
  {
    Elem * elem = _mesh._mesh.add_elem (new Edge2);
    elem->subdomain_id() = _subdomain_id;
    elem->set_node(0) = _mesh._mesh.node_ptr(node_ids[i]);
    elem->set_node(1) = _mesh._mesh.node_ptr(node_ids[i+1]);
    elem_ids.push_back(elem->id());

    // BCs
    if (i == 0)
    {
      _bnd_ids[RELAP7::IN] = bc_id_in;
      _mesh._mesh.boundary_info->add_side(elem, 0, bc_id_in);
      _bnd_nodes[RELAP7::IN] = elem->get_node(0);                // first 0 is local bnd_id that Joints will use for connecting
      _bnd_out_norm[RELAP7::IN] = -1;
    }
    if (i == (_n_elems - 1))
    {
      _bnd_ids[RELAP7::OUT] = bc_id_out;
      _mesh._mesh.boundary_info->add_side(elem, 1, bc_id_out);
      _bnd_nodes[RELAP7::OUT] = elem->get_node(1);               // first 1 is local bnd_id that Joints will use for connecting
      _bnd_out_norm[RELAP7::OUT] = 1;
    }
 }
}

void
PipeBase::addVariables()
{
  Model::addVariables(_subdomain_id);

  const EquationOfState & eos = _sim.getEquationOfState(getParam<UserObjectName>("eos"));

  Real initial_P = _sim.getParam<Real>("global_init_P");
  Real initial_V = _sim.getParam<Real>("global_init_V");
  Real initial_T = _sim.getParam<Real>("global_init_T");
  if(_has_initial_P)
    initial_P = _initial_P;			//replace by local initial conditions
  if(_has_initial_V)
    initial_V = _initial_V;
  if(_has_initial_T)
   initial_T = _initial_T;

  Real initial_rho = 0.;
  Real initial_rhou = 0.;
  Real initial_e = 0.;
  Real initial_rhoE = 0.;
  Real initial_enthalpy = 0.;
  if(_model_type == EQ_MODEL_2)
  {
    initial_rho = eos.invert_eos_rho(initial_P);
    initial_rhou = initial_rho * initial_V;
  }
  else if(_model_type == EQ_MODEL_3)
  {
    initial_e = eos.invert_eos_internal_energy(initial_T);
    initial_rho = eos.invert_eos_rho(initial_P, initial_e);
    initial_rhou = initial_rho * initial_V;
    initial_rhoE = initial_rho * initial_e + initial_rho * 0.5 * initial_V * initial_V;
    initial_enthalpy = (initial_rhoE + initial_P) / initial_rho;
  }
  else
    mooseError("wrong model type");

  Model::addInitialConditions(_subdomain_id, initial_P, initial_V, initial_rho, initial_rhou, initial_T, initial_rhoE, initial_enthalpy);
}

void
PipeBase::addMooseObjects()
{
  std::vector<unsigned int> blocks(1, _subdomain_id);

  InputParameters pars = emptyInputParameters();
  pars.set<std::vector<unsigned int> >("block") = blocks;

  pars.set<Real>("gx") = _gx;
  pars.set<Real>("g") = _g; // gravity constant
  pars.set<Real>("dh") = _Dh;
  pars.set<Real>("roughness") = _roughness;
  pars.set<Real>("aw") = _aw;
  if (_has_f)
    pars.set<Real>("f") = _f;
  if(_has_Hw)
    pars.set<Real>("Hw") = _Hw;
  pars.set<Real>("Tw") = _Tw;
  pars.set<unsigned int>("HT_geometry_code") = _HT_geometry_code;
  if (_has_PoD)
    pars.set<Real>("PoD") = _PoD;
  pars.set<UserObjectName>("eos") = getParam<UserObjectName>("eos");

  Model::addKernels(pars);

  if (_model_type == EQ_MODEL_3)
  {
    // for 3 eqn model, add wall heating term

    std::vector<std::string> cv_rho(1, RHO);
    std::vector<std::string> cv_temperature(1, TEMPERATURE);

    InputParameters params = Factory::instance()->getValidParams("OneDEnergyWallHeating");
    params.set<NonlinearVariableName>("variable") = Model::RHOE;
    params.set<std::vector<unsigned int> >("block") = blocks;

    params.set<Real>("Hw") = _Hw;
    params.set<Real>("aw") = _aw;
    params.set<Real>("Tw") = _Tw;

    params.set<std::vector<std::string> >("rho") = cv_rho;
    params.set<std::vector<std::string> >("temperature") = cv_temperature;

    std::string mon = genName(name(), _id, "_pipe");
    _sim.addKernel("OneDEnergyWallHeating", mon, params);
    connectObject("", mon);
  }
}
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "Downloads.h"

/* common implementation headers */
#include "network.h"
#include "Address.h"
#include "AccessList.h"
#include "CacheManager.h"
#include "BzMaterial.h"
#include "URLManager.h"
#include "AnsiCodes.h"
#include "TextureManager.h"

/* local implementation headers */
#include "playing.h"
#include "HUDDialogStack.h"

// FIXME - someone write a better explanation
static const char DownloadContent[] =
  "#\n"
  "# This file controls the access to servers for downloads.\n"
  "# Patterns are attempted in order against both the hostname\n"
  "# and ip. The first matching pattern sets the state. If no\n"
  "# patterns are matched, then the server is authorized. There\n"
  "# are four types of matches:\n"
  "#\n"
  "#   simple globbing (* and ?)\n"
  "#     allow\n"
  "#     deny\n"
  "#\n"
  "#   regular expressions\n"
  "#     allow_regex\n"
  "#     deny_regex\n"
  "#\n"
  "\n"
  "#\n"
  "# To authorize all servers, remove the last 3 lines.\n"
  "#\n"
  "\n"
  "allow *.bzflag.bz\n"
  "allow *.bzflag.org\n"
  "deny *\n";

static AccessList DownloadAccessList("DownloadAccess.txt", DownloadContent);

/******************************************************************************/
#ifdef HAVE_CURL
/******************************************************************************/

// Function Prototypes
static void printAuthNotice();
static bool getFileTime(const std::string& url, time_t& t);
static bool getAndCacheURL(const std::string& url);
static bool authorizedServer(const std::string& url);
static void setHudMessage(const std::string& msg);

void Downloads::doDownloads()
{
  CACHEMGR.loadIndex();
  CACHEMGR.limitCacheSize();

  DownloadAccessList.reload();

  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, false /* ignore referencing */);

  bool authNotice = false;

  const bool doDownloads =	BZDB.isTrue("doDownloads");
  const bool updateDownloads =  BZDB.isTrue("updateDownloads");

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {

      // check access authorization
      if (!authorizedServer(texUrl)) {
        MATERIALMGR.setTextureLocal(texUrl, "");
        authNotice = true;
        continue;
      }

      // use the cache?
      CacheManager::CacheRecord oldrec;
      if (CACHEMGR.findURL(texUrl, oldrec)) {
        time_t filetime = 0;
        if (doDownloads && updateDownloads) {
          getFileTime(texUrl, filetime);
        }
        if (filetime <= oldrec.date) {
          // use the cached file
          MATERIALMGR.setTextureLocal(texUrl, oldrec.name);
          continue;
        }
      }

      // bail here if we can't download
      if (!doDownloads) {
        MATERIALMGR.setTextureLocal(texUrl, "");
        std::string msg = ColorStrings[GreyColor];
        msg += "not downloading: " + texUrl;
        addMessage(NULL, msg);
        continue;
      }

      // download and cache the URL
      if (getAndCacheURL(texUrl)) {
        const std::string localname = CACHEMGR.getLocalName(texUrl);
        MATERIALMGR.setTextureLocal(texUrl, localname);
      } else {
        MATERIALMGR.setTextureLocal(texUrl, "");
      }
    }
  }

  if (authNotice) {
    printAuthNotice();
  }

  CACHEMGR.saveIndex();

  return;
}

bool Downloads::updateDownloads(bool& rebuild)
{
  CACHEMGR.loadIndex();
  CACHEMGR.limitCacheSize();

  DownloadAccessList.reload();

  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, true /* only referenced materials */);

  TextureManager& TEXMGR = TextureManager::instance();

  rebuild = false;
  bool updated = false;
  bool authNotice = false;

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {

      // check access authorization
      if (!authorizedServer(texUrl)) {
        MATERIALMGR.setTextureLocal(texUrl, "");
        authNotice = true;
        continue;
      }

      // use the cache or update?
      CacheManager::CacheRecord oldrec;
      if (CACHEMGR.findURL(texUrl, oldrec)) {
        time_t filetime;
        getFileTime(texUrl, filetime);
        if (filetime <= oldrec.date) {
          // keep using the cached file
          MATERIALMGR.setTextureLocal(texUrl, oldrec.name);
          if (!TEXMGR.isLoaded(oldrec.name)) {
            rebuild = true;
          }
          continue;
        }
      }

      // download the file and update the cache
      if (getAndCacheURL(texUrl)) {
        updated = true;
        const std::string localname = CACHEMGR.getLocalName(texUrl);
        if (!TEXMGR.isLoaded(localname)) {
          rebuild = true;
        } else {
          TEXMGR.reloadTextureImage(localname); // reload with the new image
        }
        MATERIALMGR.setTextureLocal(texUrl, localname); // if it wasn't cached
      }
    }
  }

  if (authNotice) {
    printAuthNotice();
  }

  CACHEMGR.saveIndex();

  return updated;
}

void Downloads::removeTextures()
{
  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, false /* ignore referencing */);

  TextureManager& TEXMGR = TextureManager::instance();

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {
      const std::string& localname = CACHEMGR.getLocalName(texUrl);
      if (TEXMGR.isLoaded(localname)) {
        TEXMGR.removeTexture(localname);
      }
    }
  }

  return;
}

static void printAuthNotice()
{
  std::string msg = ColorStrings[WhiteColor];
  msg += "NOTE: ";
  msg += ColorStrings[GreyColor];
  msg += "download access is controlled by ";
  msg += ColorStrings[YellowColor];
  msg += DownloadAccessList.getFileName();
  addMessage(NULL, msg);
  return;
}

static bool getFileTime(const std::string& url, time_t& t)
{
  setHudMessage("Download DNS check...");

  URLManager& URLMGR = URLManager::instance();
  if (URLMGR.getURLHeader(url)) {
    URLMGR.getFileTime(t);
    return true;
  } else {
    t = 0;
    return false;
  }

  setHudMessage("");
}

static bool getAndCacheURL(const std::string& url)
{
  bool result = false;

  setHudMessage("Download DNS check...");

  URLManager& URLMGR = URLManager::instance();
  URLMGR.setProgressFunc(curlProgressFunc, NULL);

  std::string msg = ColorStrings[GreyColor];
  msg += "downloading: " + url;
  addMessage(NULL, msg);

  void* urlData;
  unsigned int urlSize;

  if (URLMGR.getURL(url, &urlData, urlSize)) {
    time_t filetime;
    URLMGR.getFileTime(filetime);
    // CACHEMGR generates name, usedDate, and key
    CacheManager::CacheRecord rec;
    rec.url = url;
    rec.size = urlSize;
    rec.date = filetime;
    CACHEMGR.addFile(rec, urlData);
    free(urlData);
    result = true;
  }
  else {
    std::string msg = ColorStrings[RedColor] + "* failure *";
    addMessage(NULL, msg);
    result = false;
  }

  URLMGR.setProgressFunc(NULL, NULL);

  setHudMessage("");

  return result;
}

static bool authorizedServer(const std::string& url)
{
  // avoid the DNS lookup
  if (DownloadAccessList.alwaysAuthorized()) {
    return true;
  }

  // parse url
  std::string protocol, hostname, path, ip;
  int port = 1;
  if (BzfNetwork::parseURL(url, protocol, hostname, port, path) &&
      ((protocol == "http") || (protocol == "ftp")) &&
      (port >= 1) && (port <= 65535)) {
    setHudMessage("Access DNS check...");
    Address address(hostname); // get the address  (BLOCKING)
    ip = address.getDotNotation();
    setHudMessage("");
  }

  // make the list of strings to check
  std::vector<std::string> nameAndIp;
  if (hostname.size() > 0) {
    nameAndIp.push_back(hostname);
  }
  if (ip.size() > 0) {
    nameAndIp.push_back(ip);
  }

  // check and print error if not authorized
  if (!DownloadAccessList.authorized(nameAndIp)) {
    std::string msg = ColorStrings[RedColor];
    msg += "local server denial: ";
    msg += ColorStrings[GreyColor];
    msg += url;
    addMessage(NULL, msg);
    return false;
  }

  return true;
}

static void setHudMessage(const std::string& msg)
{
  HUDDialogStack::get()->setFailedMessage(msg.c_str());
  drawFrame(0.0f);
  return;
}

/******************************************************************************/
#else // ! HAVE_CURL
/******************************************************************************/

void Downloads::doDownloads()
{
  bool needWarning = false;
  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, true);

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {
      needWarning = true;
      // one time warning
      std::string msg = ColorStrings[GreyColor];
      msg += "not downloading: " + texUrl;
      addMessage(NULL, msg);
      // avoid future warnings
      MATERIALMGR.setTextureLocal(texUrl, "");
    }
  }

  if (needWarning && BZDB.isTrue("doDownloads")) {
    std::string msg = ColorStrings[RedColor];
    msg += "Downloads are not available for clients without libcurl";
    addMessage(NULL, msg);
    msg = ColorStrings[YellowColor];
    msg += "To disable this message, disable [Automatic Downloads] in";
    addMessage(NULL, msg);
    msg = ColorStrings[YellowColor];
    msg += "Options -> Cache Options, or get a client with libcurl";
    addMessage(NULL, msg);
  }

  return;
}

bool Downloads::updateDownloads(bool& /*rebuild*/)
{
  std::string msg = ColorStrings[RedColor];
  msg += "Downloads are not available for clients without libcurl";
  addMessage(NULL, msg);
  return false;
}

/******************************************************************************/
#endif // HAVE_CURL
/******************************************************************************/

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>removeTextures() is declared but was only previously defined for HAVE_CURL, just make a placeholder so it builds for no HAVE_CURL builds<commit_after>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "Downloads.h"

/* common implementation headers */
#include "network.h"
#include "Address.h"
#include "AccessList.h"
#include "CacheManager.h"
#include "BzMaterial.h"
#include "URLManager.h"
#include "AnsiCodes.h"
#include "TextureManager.h"

/* local implementation headers */
#include "playing.h"
#include "HUDDialogStack.h"

// FIXME - someone write a better explanation
static const char DownloadContent[] =
  "#\n"
  "# This file controls the access to servers for downloads.\n"
  "# Patterns are attempted in order against both the hostname\n"
  "# and ip. The first matching pattern sets the state. If no\n"
  "# patterns are matched, then the server is authorized. There\n"
  "# are four types of matches:\n"
  "#\n"
  "#   simple globbing (* and ?)\n"
  "#     allow\n"
  "#     deny\n"
  "#\n"
  "#   regular expressions\n"
  "#     allow_regex\n"
  "#     deny_regex\n"
  "#\n"
  "\n"
  "#\n"
  "# To authorize all servers, remove the last 3 lines.\n"
  "#\n"
  "\n"
  "allow *.bzflag.bz\n"
  "allow *.bzflag.org\n"
  "deny *\n";

static AccessList DownloadAccessList("DownloadAccess.txt", DownloadContent);

/******************************************************************************/
#ifdef HAVE_CURL
/******************************************************************************/

// Function Prototypes
static void printAuthNotice();
static bool getFileTime(const std::string& url, time_t& t);
static bool getAndCacheURL(const std::string& url);
static bool authorizedServer(const std::string& url);
static void setHudMessage(const std::string& msg);

void Downloads::doDownloads()
{
  CACHEMGR.loadIndex();
  CACHEMGR.limitCacheSize();

  DownloadAccessList.reload();

  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, false /* ignore referencing */);

  bool authNotice = false;

  const bool doDownloads =	BZDB.isTrue("doDownloads");
  const bool updateDownloads =  BZDB.isTrue("updateDownloads");

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {

      // check access authorization
      if (!authorizedServer(texUrl)) {
        MATERIALMGR.setTextureLocal(texUrl, "");
        authNotice = true;
        continue;
      }

      // use the cache?
      CacheManager::CacheRecord oldrec;
      if (CACHEMGR.findURL(texUrl, oldrec)) {
        time_t filetime = 0;
        if (doDownloads && updateDownloads) {
          getFileTime(texUrl, filetime);
        }
        if (filetime <= oldrec.date) {
          // use the cached file
          MATERIALMGR.setTextureLocal(texUrl, oldrec.name);
          continue;
        }
      }

      // bail here if we can't download
      if (!doDownloads) {
        MATERIALMGR.setTextureLocal(texUrl, "");
        std::string msg = ColorStrings[GreyColor];
        msg += "not downloading: " + texUrl;
        addMessage(NULL, msg);
        continue;
      }

      // download and cache the URL
      if (getAndCacheURL(texUrl)) {
        const std::string localname = CACHEMGR.getLocalName(texUrl);
        MATERIALMGR.setTextureLocal(texUrl, localname);
      } else {
        MATERIALMGR.setTextureLocal(texUrl, "");
      }
    }
  }

  if (authNotice) {
    printAuthNotice();
  }

  CACHEMGR.saveIndex();

  return;
}

bool Downloads::updateDownloads(bool& rebuild)
{
  CACHEMGR.loadIndex();
  CACHEMGR.limitCacheSize();

  DownloadAccessList.reload();

  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, true /* only referenced materials */);

  TextureManager& TEXMGR = TextureManager::instance();

  rebuild = false;
  bool updated = false;
  bool authNotice = false;

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {

      // check access authorization
      if (!authorizedServer(texUrl)) {
        MATERIALMGR.setTextureLocal(texUrl, "");
        authNotice = true;
        continue;
      }

      // use the cache or update?
      CacheManager::CacheRecord oldrec;
      if (CACHEMGR.findURL(texUrl, oldrec)) {
        time_t filetime;
        getFileTime(texUrl, filetime);
        if (filetime <= oldrec.date) {
          // keep using the cached file
          MATERIALMGR.setTextureLocal(texUrl, oldrec.name);
          if (!TEXMGR.isLoaded(oldrec.name)) {
            rebuild = true;
          }
          continue;
        }
      }

      // download the file and update the cache
      if (getAndCacheURL(texUrl)) {
        updated = true;
        const std::string localname = CACHEMGR.getLocalName(texUrl);
        if (!TEXMGR.isLoaded(localname)) {
          rebuild = true;
        } else {
          TEXMGR.reloadTextureImage(localname); // reload with the new image
        }
        MATERIALMGR.setTextureLocal(texUrl, localname); // if it wasn't cached
      }
    }
  }

  if (authNotice) {
    printAuthNotice();
  }

  CACHEMGR.saveIndex();

  return updated;
}

void Downloads::removeTextures()
{
  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, false /* ignore referencing */);

  TextureManager& TEXMGR = TextureManager::instance();

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {
      const std::string& localname = CACHEMGR.getLocalName(texUrl);
      if (TEXMGR.isLoaded(localname)) {
        TEXMGR.removeTexture(localname);
      }
    }
  }

  return;
}

static void printAuthNotice()
{
  std::string msg = ColorStrings[WhiteColor];
  msg += "NOTE: ";
  msg += ColorStrings[GreyColor];
  msg += "download access is controlled by ";
  msg += ColorStrings[YellowColor];
  msg += DownloadAccessList.getFileName();
  addMessage(NULL, msg);
  return;
}

static bool getFileTime(const std::string& url, time_t& t)
{
  setHudMessage("Download DNS check...");

  URLManager& URLMGR = URLManager::instance();
  if (URLMGR.getURLHeader(url)) {
    URLMGR.getFileTime(t);
    return true;
  } else {
    t = 0;
    return false;
  }

  setHudMessage("");
}

static bool getAndCacheURL(const std::string& url)
{
  bool result = false;

  setHudMessage("Download DNS check...");

  URLManager& URLMGR = URLManager::instance();
  URLMGR.setProgressFunc(curlProgressFunc, NULL);

  std::string msg = ColorStrings[GreyColor];
  msg += "downloading: " + url;
  addMessage(NULL, msg);

  void* urlData;
  unsigned int urlSize;

  if (URLMGR.getURL(url, &urlData, urlSize)) {
    time_t filetime;
    URLMGR.getFileTime(filetime);
    // CACHEMGR generates name, usedDate, and key
    CacheManager::CacheRecord rec;
    rec.url = url;
    rec.size = urlSize;
    rec.date = filetime;
    CACHEMGR.addFile(rec, urlData);
    free(urlData);
    result = true;
  }
  else {
    std::string msg = ColorStrings[RedColor] + "* failure *";
    addMessage(NULL, msg);
    result = false;
  }

  URLMGR.setProgressFunc(NULL, NULL);

  setHudMessage("");

  return result;
}

static bool authorizedServer(const std::string& url)
{
  // avoid the DNS lookup
  if (DownloadAccessList.alwaysAuthorized()) {
    return true;
  }

  // parse url
  std::string protocol, hostname, path, ip;
  int port = 1;
  if (BzfNetwork::parseURL(url, protocol, hostname, port, path) &&
      ((protocol == "http") || (protocol == "ftp")) &&
      (port >= 1) && (port <= 65535)) {
    setHudMessage("Access DNS check...");
    Address address(hostname); // get the address  (BLOCKING)
    ip = address.getDotNotation();
    setHudMessage("");
  }

  // make the list of strings to check
  std::vector<std::string> nameAndIp;
  if (hostname.size() > 0) {
    nameAndIp.push_back(hostname);
  }
  if (ip.size() > 0) {
    nameAndIp.push_back(ip);
  }

  // check and print error if not authorized
  if (!DownloadAccessList.authorized(nameAndIp)) {
    std::string msg = ColorStrings[RedColor];
    msg += "local server denial: ";
    msg += ColorStrings[GreyColor];
    msg += url;
    addMessage(NULL, msg);
    return false;
  }

  return true;
}

static void setHudMessage(const std::string& msg)
{
  HUDDialogStack::get()->setFailedMessage(msg.c_str());
  drawFrame(0.0f);
  return;
}

/******************************************************************************/
#else // ! HAVE_CURL
/******************************************************************************/

void Downloads::doDownloads()
{
  bool needWarning = false;
  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, true);

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {
      needWarning = true;
      // one time warning
      std::string msg = ColorStrings[GreyColor];
      msg += "not downloading: " + texUrl;
      addMessage(NULL, msg);
      // avoid future warnings
      MATERIALMGR.setTextureLocal(texUrl, "");
    }
  }

  if (needWarning && BZDB.isTrue("doDownloads")) {
    std::string msg = ColorStrings[RedColor];
    msg += "Downloads are not available for clients without libcurl";
    addMessage(NULL, msg);
    msg = ColorStrings[YellowColor];
    msg += "To disable this message, disable [Automatic Downloads] in";
    addMessage(NULL, msg);
    msg = ColorStrings[YellowColor];
    msg += "Options -> Cache Options, or get a client with libcurl";
    addMessage(NULL, msg);
  }

  return;
}

bool Downloads::updateDownloads(bool& /*rebuild*/)
{
  std::string msg = ColorStrings[RedColor];
  msg += "Downloads are not available for clients without libcurl";
  addMessage(NULL, msg);
  return false;
}

void Downloads::removeTextures()
{
  /* FIXME: just a placeholder as this function is declared but only defined for
     HAVE_CURL building */
  return;
}

/******************************************************************************/
#endif // HAVE_CURL
/******************************************************************************/

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "Downloads.h"

/* system headers */
#include <map>

/* common implementation headers */
#include "network.h"
#include "Address.h"
#include "AccessList.h"
#include "CacheManager.h"
#include "BzMaterial.h"
#include "URLManager.h"
#include "AnsiCodes.h"
#include "TextureManager.h"

/* local implementation headers */
#include "playing.h"
#include "HUDDialogStack.h"

// FIXME - someone write a better explanation
static const char DownloadContent[] =
  "#\n"
  "# This file controls the access to servers for downloads.\n"
  "# Patterns are attempted in order against both the hostname\n"
  "# and ip. The first matching pattern sets the state. If no\n"
  "# patterns are matched, then the server is authorized. There\n"
  "# are four types of matches:\n"
  "#\n"
  "#   simple globbing (* and ?)\n"
  "#     allow\n"
  "#     deny\n"
  "#\n"
  "#   regular expressions\n"
  "#     allow_regex\n"
  "#     deny_regex\n"
  "#\n"
  "\n"
  "#\n"
  "# To authorize all servers, remove the last 3 lines.\n"
  "#\n"
  "\n"
  "allow *.bzflag.bz\n"
  "allow *.bzflag.org\n"
  "deny *\n";

static AccessList DownloadAccessList("DownloadAccess.txt", DownloadContent);

/******************************************************************************/
#ifdef HAVE_CURL
/******************************************************************************/

// Function Prototypes
static void printAuthNotice();
static void setHudMessage(const std::string& msg);
static bool getFileTime(const std::string& url, time_t& t);
static bool getAndCacheURL(const std::string& url);
static bool authorizedServer(const std::string& hostname);
static bool checkAuthorizations(BzMaterialManager::TextureSet& set);

void Downloads::doDownloads()
{
  CACHEMGR.loadIndex();
  CACHEMGR.limitCacheSize();

  DownloadAccessList.reload();

  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, false /* ignore referencing */);

  const bool doDownloads =	BZDB.isTrue("doDownloads");
  const bool updateDownloads =  BZDB.isTrue("updateDownloads");

  // check hosts' access permissions
  bool authNotice = checkAuthorizations(set);

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {

      // use the cache?
      CacheManager::CacheRecord oldrec;
      if (CACHEMGR.findURL(texUrl, oldrec)) {
	time_t filetime = 0;
	if (doDownloads && updateDownloads) {
	  getFileTime(texUrl, filetime);
	}
	if (filetime <= oldrec.date) {
	  // use the cached file
	  MATERIALMGR.setTextureLocal(texUrl, oldrec.name);
	  continue;
	}
      }

      // bail here if we can't download
      if (!doDownloads) {
	MATERIALMGR.setTextureLocal(texUrl, "");
	std::string msg = ColorStrings[GreyColor];
	msg += "not downloading: " + texUrl;
	addMessage(NULL, msg);
	continue;
      }

      // download and cache the URL
      if (getAndCacheURL(texUrl)) {
	const std::string localname = CACHEMGR.getLocalName(texUrl);
	MATERIALMGR.setTextureLocal(texUrl, localname);
      } else {
	MATERIALMGR.setTextureLocal(texUrl, "");
      }
    }
  }

  if (authNotice) {
    printAuthNotice();
  }

  CACHEMGR.saveIndex();

  return;
}

bool Downloads::updateDownloads(bool& rebuild)
{
  CACHEMGR.loadIndex();
  CACHEMGR.limitCacheSize();

  DownloadAccessList.reload();

  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, true /* only referenced materials */);

  TextureManager& TEXMGR = TextureManager::instance();

  rebuild = false;
  bool updated = false;

  // check hosts' access permissions
  bool authNotice = checkAuthorizations(set);

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {

      // use the cache or update?
      CacheManager::CacheRecord oldrec;
      if (CACHEMGR.findURL(texUrl, oldrec)) {
	time_t filetime;
	getFileTime(texUrl, filetime);
	if (filetime <= oldrec.date) {
	  // keep using the cached file
	  MATERIALMGR.setTextureLocal(texUrl, oldrec.name);
	  if (!TEXMGR.isLoaded(oldrec.name)) {
	    rebuild = true;
	  }
	  continue;
	}
      }

      // download the file and update the cache
      if (getAndCacheURL(texUrl)) {
	updated = true;
	const std::string localname = CACHEMGR.getLocalName(texUrl);
	if (!TEXMGR.isLoaded(localname)) {
	  rebuild = true;
	} else {
	  TEXMGR.reloadTextureImage(localname); // reload with the new image
	}
	MATERIALMGR.setTextureLocal(texUrl, localname); // if it wasn't cached
      }
    }
  }

  if (authNotice) {
    printAuthNotice();
  }

  CACHEMGR.saveIndex();

  return updated;
}

void Downloads::removeTextures()
{
  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, false /* ignore referencing */);

  TextureManager& TEXMGR = TextureManager::instance();

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {
      const std::string& localname = CACHEMGR.getLocalName(texUrl);
      if (TEXMGR.isLoaded(localname)) {
	TEXMGR.removeTexture(localname);
      }
    }
  }

  return;
}

static void printAuthNotice()
{
  std::string msg = ColorStrings[WhiteColor];
  msg += "NOTE: ";
  msg += ColorStrings[GreyColor];
  msg += "download access is controlled by ";
  msg += ColorStrings[YellowColor];
  msg += DownloadAccessList.getFileName();
  addMessage(NULL, msg);
  return;
}

static bool getFileTime(const std::string& url, time_t& t)
{
  setHudMessage("Update DNS check...");

  URLManager& URLMGR = URLManager::instance();
  if (URLMGR.getURLHeader(url)) {
    URLMGR.getFileTime(t);
    return true;
  } else {
    t = 0;
    return false;
  }

  setHudMessage("");
}

static bool getAndCacheURL(const std::string& url)
{
  bool result = false;

  setHudMessage("Download DNS check...");

  URLManager& URLMGR = URLManager::instance();
  URLMGR.setProgressFunc(curlProgressFunc, NULL);

  std::string msg = ColorStrings[GreyColor];
  msg += "downloading: " + url;
  addMessage(NULL, msg);

  void* urlData;
  unsigned int urlSize;

  if (URLMGR.getURL(url, &urlData, urlSize)) {
    time_t filetime;
    URLMGR.getFileTime(filetime);
    // CACHEMGR generates name, usedDate, and key
    CacheManager::CacheRecord rec;
    rec.url = url;
    rec.size = urlSize;
    rec.date = filetime;
    CACHEMGR.addFile(rec, urlData);
    free(urlData);
    result = true;
  }
  else {
    std::string msg = ColorStrings[RedColor] + "failure: ";
    msg += URLMGR.getErrorString();
    addMessage(NULL, msg);
    result = false;
  }

  URLMGR.setProgressFunc(NULL, NULL);

  setHudMessage("");

  return result;
}

static bool authorizedServer(const std::string& hostname)
{
  setHudMessage("Access DNS check...");
  Address address(hostname); // get the address  (BLOCKING)
  std::string ip = address.getDotNotation();
  setHudMessage("");

  // make the list of strings to check
  std::vector<std::string> nameAndIp;
  if (hostname.size() > 0) {
    nameAndIp.push_back(hostname);
  }
  if (ip.size() > 0) {
    nameAndIp.push_back(ip);
  }

  return DownloadAccessList.authorized(nameAndIp);
}

static bool parseHostname(const std::string& url, std::string& hostname)
{
  std::string protocol, path, ip;
  int port;
  if (BzfNetwork::parseURL(url, protocol, hostname, port, path)) {
    if ((protocol == "http") || (protocol == "ftp")) {
      return true;
    }
  }
  return false;
}

static bool checkAuthorizations(BzMaterialManager::TextureSet& set)
{
  // avoid the DNS lookup
  if (DownloadAccessList.alwaysAuthorized()) {
    return false;
  }

  bool hostFailed = false;

  BzMaterialManager::TextureSet::iterator set_it;

  std::map<std::string, bool> hostAccess;
  std::map<std::string, bool>::iterator host_it;

  // get the list of hosts to check
  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& url = *set_it;
    std::string hostname;
    if (parseHostname(url, hostname)) {
      hostAccess[hostname] = true;
    }
  }

  // check the hosts
  for (host_it = hostAccess.begin(); host_it != hostAccess.end(); host_it++) {
    const std::string& host = host_it->first;
    host_it->second = authorizedServer(host);
  }

  // clear any unauthorized urls
  set_it = set.begin();
  while (set_it != set.end()) {
    BzMaterialManager::TextureSet::iterator next_it = set_it;
    next_it++;
    const std::string& url = *set_it;
    std::string hostname;
    if (parseHostname(url, hostname) && !hostAccess[hostname]) {
      hostFailed = true;
      // send a message
      std::string msg = ColorStrings[RedColor];
      msg += "local denial: ";
      msg += ColorStrings[GreyColor];
      msg += url;
      addMessage(NULL, msg);
      // remove the url
      MATERIALMGR.setTextureLocal(url, "");
      set.erase(set_it);
    }
    set_it = next_it;
  }

  return hostFailed;
}

static void setHudMessage(const std::string& msg)
{
  HUDDialogStack::get()->setFailedMessage(msg.c_str());
  drawFrame(0.0f);
  return;
}

/******************************************************************************/
#else // ! HAVE_CURL
/******************************************************************************/

void Downloads::doDownloads()
{
  bool needWarning = false;
  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, false /* ignore referencing */);

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {
      needWarning = true;
      // one time warning
      std::string msg = ColorStrings[GreyColor];
      msg += "not downloading: " + texUrl;
      addMessage(NULL, msg);
      // avoid future warnings
      MATERIALMGR.setTextureLocal(texUrl, "");
    }
  }

  if (needWarning && BZDB.isTrue("doDownloads")) {
    std::string msg = ColorStrings[RedColor];
    msg += "Downloads are not available for clients without libcurl";
    addMessage(NULL, msg);
    msg = ColorStrings[YellowColor];
    msg += "To disable this message, disable [Automatic Downloads] in";
    addMessage(NULL, msg);
    msg = ColorStrings[YellowColor];
    msg += "Options -> Cache Options, or get a client with libcurl";
    addMessage(NULL, msg);
  }

  return;
}

bool Downloads::updateDownloads(bool& /*rebuild*/)
{
  std::string msg = ColorStrings[RedColor];
  msg += "Downloads are not available for clients without libcurl";
  addMessage(NULL, msg);
  return false;
}

void Downloads::removeTextures()
{
  return;
}

/******************************************************************************/
#endif // HAVE_CURL
/******************************************************************************/

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>Before curl, rewrite a little<commit_after>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "Downloads.h"

/* system headers */
#include <map>

/* common implementation headers */
#include "network.h"
#include "Address.h"
#include "AccessList.h"
#include "CacheManager.h"
#include "BzMaterial.h"
#include "URLManager.h"
#include "AnsiCodes.h"
#include "TextureManager.h"

/* local implementation headers */
#include "playing.h"
#include "HUDDialogStack.h"

// FIXME - someone write a better explanation
static const char DownloadContent[] =
  "#\n"
  "# This file controls the access to servers for downloads.\n"
  "# Patterns are attempted in order against both the hostname\n"
  "# and ip. The first matching pattern sets the state. If no\n"
  "# patterns are matched, then the server is authorized. There\n"
  "# are four types of matches:\n"
  "#\n"
  "#   simple globbing (* and ?)\n"
  "#     allow\n"
  "#     deny\n"
  "#\n"
  "#   regular expressions\n"
  "#     allow_regex\n"
  "#     deny_regex\n"
  "#\n"
  "\n"
  "#\n"
  "# To authorize all servers, remove the last 3 lines.\n"
  "#\n"
  "\n"
  "allow *.bzflag.bz\n"
  "allow *.bzflag.org\n"
  "deny *\n";

static AccessList DownloadAccessList("DownloadAccess.txt", DownloadContent);

/******************************************************************************/
#ifdef HAVE_CURL
/******************************************************************************/

// Function Prototypes
static void printAuthNotice();
static void setHudMessage(const std::string& msg);
static bool getFileTime(const std::string& url, time_t& t);
static bool getAndCacheURL(const std::string& url);
static bool authorizedServer(const std::string& hostname);
static bool checkAuthorizations(BzMaterialManager::TextureSet& set);

void Downloads::doDownloads()
{
  CACHEMGR.loadIndex();
  CACHEMGR.limitCacheSize();

  DownloadAccessList.reload();

  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, false /* ignore referencing */);

  const bool doDownloads =	BZDB.isTrue("doDownloads");
  const bool updateDownloads =  BZDB.isTrue("updateDownloads");

  // check hosts' access permissions
  bool authNotice = checkAuthorizations(set);

  if (!doDownloads) {
    // bail here if we can't download
    for (set_it = set.begin(); set_it != set.end(); set_it++) {
      const std::string& texUrl = set_it->c_str();
      if (CACHEMGR.isCacheFileType(texUrl)) {
	MATERIALMGR.setTextureLocal(texUrl, "");
	std::string msg = ColorStrings[GreyColor];
	msg += "not downloading: " + texUrl;
	addMessage(NULL, msg);
      }
    }
  } else {
    for (set_it = set.begin(); set_it != set.end(); set_it++) {
      const std::string& texUrl = set_it->c_str();
      if (CACHEMGR.isCacheFileType(texUrl)) {

	// use the cache?
	CacheManager::CacheRecord oldrec;
	if (CACHEMGR.findURL(texUrl, oldrec)) {
	  time_t filetime = 0;
	  if (updateDownloads) {
	    getFileTime(texUrl, filetime);
	    if (filetime <= oldrec.date) {
	      // use the cached file
	      MATERIALMGR.setTextureLocal(texUrl, oldrec.name);
	      continue;
	    }
	  }
	}

	// download and cache the URL
	if (getAndCacheURL(texUrl)) {
	  const std::string localname = CACHEMGR.getLocalName(texUrl);
	  MATERIALMGR.setTextureLocal(texUrl, localname);
	} else {
	  MATERIALMGR.setTextureLocal(texUrl, "");
	}
      }
    }
  }

  if (authNotice) {
    printAuthNotice();
  }

  CACHEMGR.saveIndex();

  return;
}

bool Downloads::updateDownloads(bool& rebuild)
{
  CACHEMGR.loadIndex();
  CACHEMGR.limitCacheSize();

  DownloadAccessList.reload();

  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, true /* only referenced materials */);

  TextureManager& TEXMGR = TextureManager::instance();

  rebuild = false;
  bool updated = false;

  // check hosts' access permissions
  bool authNotice = checkAuthorizations(set);

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {

      // use the cache or update?
      CacheManager::CacheRecord oldrec;
      if (CACHEMGR.findURL(texUrl, oldrec)) {
	time_t filetime;
	getFileTime(texUrl, filetime);
	if (filetime <= oldrec.date) {
	  // keep using the cached file
	  MATERIALMGR.setTextureLocal(texUrl, oldrec.name);
	  if (!TEXMGR.isLoaded(oldrec.name)) {
	    rebuild = true;
	  }
	  continue;
	}
      }

      // download the file and update the cache
      if (getAndCacheURL(texUrl)) {
	updated = true;
	const std::string localname = CACHEMGR.getLocalName(texUrl);
	if (!TEXMGR.isLoaded(localname)) {
	  rebuild = true;
	} else {
	  TEXMGR.reloadTextureImage(localname); // reload with the new image
	}
	MATERIALMGR.setTextureLocal(texUrl, localname); // if it wasn't cached
      }
    }
  }

  if (authNotice) {
    printAuthNotice();
  }

  CACHEMGR.saveIndex();

  return updated;
}

void Downloads::removeTextures()
{
  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, false /* ignore referencing */);

  TextureManager& TEXMGR = TextureManager::instance();

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {
      const std::string& localname = CACHEMGR.getLocalName(texUrl);
      if (TEXMGR.isLoaded(localname)) {
	TEXMGR.removeTexture(localname);
      }
    }
  }

  return;
}

static void printAuthNotice()
{
  std::string msg = ColorStrings[WhiteColor];
  msg += "NOTE: ";
  msg += ColorStrings[GreyColor];
  msg += "download access is controlled by ";
  msg += ColorStrings[YellowColor];
  msg += DownloadAccessList.getFileName();
  addMessage(NULL, msg);
  return;
}

static bool getFileTime(const std::string& url, time_t& t)
{
  setHudMessage("Update DNS check...");

  URLManager& URLMGR = URLManager::instance();
  if (URLMGR.getURLHeader(url)) {
    URLMGR.getFileTime(t);
    return true;
  } else {
    t = 0;
    return false;
  }

  setHudMessage("");
}

static bool getAndCacheURL(const std::string& url)
{
  bool result = false;

  setHudMessage("Download DNS check...");

  URLManager& URLMGR = URLManager::instance();
  URLMGR.setProgressFunc(curlProgressFunc, NULL);

  std::string msg = ColorStrings[GreyColor];
  msg += "downloading: " + url;
  addMessage(NULL, msg);

  void* urlData;
  unsigned int urlSize;

  if (URLMGR.getURL(url, &urlData, urlSize)) {
    time_t filetime;
    URLMGR.getFileTime(filetime);
    // CACHEMGR generates name, usedDate, and key
    CacheManager::CacheRecord rec;
    rec.url = url;
    rec.size = urlSize;
    rec.date = filetime;
    CACHEMGR.addFile(rec, urlData);
    free(urlData);
    result = true;
  }
  else {
    std::string msg = ColorStrings[RedColor] + "failure: ";
    msg += URLMGR.getErrorString();
    addMessage(NULL, msg);
    result = false;
  }

  URLMGR.setProgressFunc(NULL, NULL);

  setHudMessage("");

  return result;
}

static bool authorizedServer(const std::string& hostname)
{
  setHudMessage("Access DNS check...");
  Address address(hostname); // get the address  (BLOCKING)
  std::string ip = address.getDotNotation();
  setHudMessage("");

  // make the list of strings to check
  std::vector<std::string> nameAndIp;
  if (hostname.size() > 0) {
    nameAndIp.push_back(hostname);
  }
  if (ip.size() > 0) {
    nameAndIp.push_back(ip);
  }

  return DownloadAccessList.authorized(nameAndIp);
}

static bool parseHostname(const std::string& url, std::string& hostname)
{
  std::string protocol, path, ip;
  int port;
  if (BzfNetwork::parseURL(url, protocol, hostname, port, path)) {
    if ((protocol == "http") || (protocol == "ftp")) {
      return true;
    }
  }
  return false;
}

static bool checkAuthorizations(BzMaterialManager::TextureSet& set)
{
  // avoid the DNS lookup
  if (DownloadAccessList.alwaysAuthorized()) {
    return false;
  }

  bool hostFailed = false;

  BzMaterialManager::TextureSet::iterator set_it;

  std::map<std::string, bool> hostAccess;
  std::map<std::string, bool>::iterator host_it;

  // get the list of hosts to check
  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& url = *set_it;
    std::string hostname;
    if (parseHostname(url, hostname)) {
      hostAccess[hostname] = true;
    }
  }

  // check the hosts
  for (host_it = hostAccess.begin(); host_it != hostAccess.end(); host_it++) {
    const std::string& host = host_it->first;
    host_it->second = authorizedServer(host);
  }

  // clear any unauthorized urls
  set_it = set.begin();
  while (set_it != set.end()) {
    BzMaterialManager::TextureSet::iterator next_it = set_it;
    next_it++;
    const std::string& url = *set_it;
    std::string hostname;
    if (parseHostname(url, hostname) && !hostAccess[hostname]) {
      hostFailed = true;
      // send a message
      std::string msg = ColorStrings[RedColor];
      msg += "local denial: ";
      msg += ColorStrings[GreyColor];
      msg += url;
      addMessage(NULL, msg);
      // remove the url
      MATERIALMGR.setTextureLocal(url, "");
      set.erase(set_it);
    }
    set_it = next_it;
  }

  return hostFailed;
}

static void setHudMessage(const std::string& msg)
{
  HUDDialogStack::get()->setFailedMessage(msg.c_str());
  drawFrame(0.0f);
  return;
}

/******************************************************************************/
#else // ! HAVE_CURL
/******************************************************************************/

void Downloads::doDownloads()
{
  bool needWarning = false;
  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, false /* ignore referencing */);

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {
      needWarning = true;
      // one time warning
      std::string msg = ColorStrings[GreyColor];
      msg += "not downloading: " + texUrl;
      addMessage(NULL, msg);
      // avoid future warnings
      MATERIALMGR.setTextureLocal(texUrl, "");
    }
  }

  if (needWarning && BZDB.isTrue("doDownloads")) {
    std::string msg = ColorStrings[RedColor];
    msg += "Downloads are not available for clients without libcurl";
    addMessage(NULL, msg);
    msg = ColorStrings[YellowColor];
    msg += "To disable this message, disable [Automatic Downloads] in";
    addMessage(NULL, msg);
    msg = ColorStrings[YellowColor];
    msg += "Options -> Cache Options, or get a client with libcurl";
    addMessage(NULL, msg);
  }

  return;
}

bool Downloads::updateDownloads(bool& /*rebuild*/)
{
  std::string msg = ColorStrings[RedColor];
  msg += "Downloads are not available for clients without libcurl";
  addMessage(NULL, msg);
  return false;
}

void Downloads::removeTextures()
{
  return;
}

/******************************************************************************/
#endif // HAVE_CURL
/******************************************************************************/

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "Downloads.h"

/* common implementation headers */
#include "network.h"
#include "Address.h"
#include "AccessList.h"
#include "CacheManager.h"
#include "BzMaterial.h"
#include "URLManager.h"
#include "AnsiCodes.h"
#include "TextureManager.h"

/* local implementation headers */
#include "playing.h"
#include "HUDDialogStack.h"

// FIXME - someone write a better explanation
static const char DownloadContent[] =
  "#\n"
  "# This file controls the access to servers for downloads.\n"
  "# Patterns are attempted in order against both the hostname\n"
  "# and ip. The first matching pattern sets the state. If no\n"
  "# patterns are matched, then the server is authorized. There\n"
  "# are four types of matches:\n"
  "#\n"
  "#   simple globbing (* and ?)\n"
  "#     allow\n"
  "#     deny\n"
  "#\n"
  "#   regular expressions\n"
  "#     allow_regex\n"
  "#     deny_regex\n"
  "#\n"
  "\n"
  "#\n"
  "# To authorize all servers, remove the last 3 lines.\n"
  "#\n"
  "\n"
  "allow *.bzflag.bz\n"
  "allow *.bzflag.org\n"
  "deny *\n";

static AccessList DownloadAccessList("DownloadAccess.txt", DownloadContent);

/******************************************************************************/
#ifdef HAVE_CURL
/******************************************************************************/

// Function Prototypes
static void printAuthNotice();
static bool getFileTime(const std::string& url, time_t& t);
static bool getAndCacheURL(const std::string& url);
static bool authorizedServer(const std::string& url);
static void setHudMessage(const std::string& msg);

void Downloads::doDownloads()
{
  CACHEMGR.loadIndex();
  CACHEMGR.limitCacheSize();

  DownloadAccessList.reload();

  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, false /* ignore referencing */);

  bool authNotice = false;

  const bool doDownloads =	BZDB.isTrue("doDownloads");
  const bool updateDownloads =  BZDB.isTrue("updateDownloads");

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {

      // check access authorization
      if (!authorizedServer(texUrl)) {
        MATERIALMGR.setTextureLocal(texUrl, "");
        authNotice = true;
        continue;
      }

      // use the cache?
      CacheManager::CacheRecord oldrec;
      if (CACHEMGR.findURL(texUrl, oldrec)) {
        time_t filetime = 0;
        if (doDownloads && updateDownloads) {
          getFileTime(texUrl, filetime);
        }
        if (filetime <= oldrec.date) {
          // use the cached file
          MATERIALMGR.setTextureLocal(texUrl, oldrec.name);
          continue;
        }
      }

      // bail here if we can't download
      if (!doDownloads) {
        MATERIALMGR.setTextureLocal(texUrl, "");
        std::string msg = ColorStrings[GreyColor];
        msg += "not downloading: " + texUrl;
        addMessage(NULL, msg);
        continue;
      }

      // download and cache the URL
      if (getAndCacheURL(texUrl)) {
        const std::string localname = CACHEMGR.getLocalName(texUrl);
        MATERIALMGR.setTextureLocal(texUrl, localname);
      } else {
        MATERIALMGR.setTextureLocal(texUrl, "");
      }
    }
  }

  if (authNotice) {
    printAuthNotice();
  }

  CACHEMGR.saveIndex();

  return;
}

bool Downloads::updateDownloads(bool& rebuild)
{
  CACHEMGR.loadIndex();
  CACHEMGR.limitCacheSize();

  DownloadAccessList.reload();

  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, true /* only referenced materials */);

  TextureManager& TEXMGR = TextureManager::instance();

  rebuild = false;
  bool updated = false;
  bool authNotice = false;

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {

      // check access authorization
      if (!authorizedServer(texUrl)) {
        MATERIALMGR.setTextureLocal(texUrl, "");
        authNotice = true;
        continue;
      }

      // use the cache or update?
      CacheManager::CacheRecord oldrec;
      if (CACHEMGR.findURL(texUrl, oldrec)) {
        time_t filetime;
        getFileTime(texUrl, filetime);
        if (filetime <= oldrec.date) {
          // keep using the cached file
          MATERIALMGR.setTextureLocal(texUrl, oldrec.name);
          if (!TEXMGR.isLoaded(oldrec.name)) {
            rebuild = true;
          }
          continue;
        }
      }

      // download the file and update the cache
      if (getAndCacheURL(texUrl)) {
        updated = true;
        const std::string localname = CACHEMGR.getLocalName(texUrl);
        if (!TEXMGR.isLoaded(localname)) {
          rebuild = true;
        } else {
          TEXMGR.reloadTextureImage(localname); // reload with the new image
        }
        MATERIALMGR.setTextureLocal(texUrl, localname); // if it wasn't cached
      }
    }
  }

  if (authNotice) {
    printAuthNotice();
  }

  CACHEMGR.saveIndex();

  return updated;
}

void Downloads::removeTextures()
{
  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, false /* ignore referencing */);

  TextureManager& TEXMGR = TextureManager::instance();

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {
      const std::string& localname = CACHEMGR.getLocalName(texUrl);
      if (TEXMGR.isLoaded(localname)) {
        TEXMGR.removeTexture(localname);
      }
    }
  }

  return;
}

static void printAuthNotice()
{
  std::string msg = ColorStrings[WhiteColor];
  msg += "NOTE: ";
  msg += ColorStrings[GreyColor];
  msg += "download access is controlled by ";
  msg += ColorStrings[YellowColor];
  msg += DownloadAccessList.getFileName();
  addMessage(NULL, msg);
  return;
}

static bool getFileTime(const std::string& url, time_t& t)
{
  setHudMessage("Download DNS check...");

  URLManager& URLMGR = URLManager::instance();
  if (URLMGR.getURLHeader(url)) {
    URLMGR.getFileTime(t);
    return true;
  } else {
    t = 0;
    return false;
  }

  setHudMessage("");
}

static bool getAndCacheURL(const std::string& url)
{
  bool result = false;

  setHudMessage("Download DNS check...");

  URLManager& URLMGR = URLManager::instance();
  URLMGR.setProgressFunc(curlProgressFunc, NULL);

  std::string msg = ColorStrings[GreyColor];
  msg += "downloading: " + url;
  addMessage(NULL, msg);

  void* urlData;
  unsigned int urlSize;

  if (URLMGR.getURL(url, &urlData, urlSize)) {
    time_t filetime;
    URLMGR.getFileTime(filetime);
    // CACHEMGR generates name, usedDate, and key
    CacheManager::CacheRecord rec;
    rec.url = url;
    rec.size = urlSize;
    rec.date = filetime;
    CACHEMGR.addFile(rec, urlData);
    free(urlData);
    result = true;
  }
  else {
    std::string msg = ColorStrings[RedColor] + "* failure *";
    addMessage(NULL, msg);
    result = false;
  }

  URLMGR.setProgressFunc(NULL, NULL);

  setHudMessage("");

  return result;
}

static bool authorizedServer(const std::string& url)
{
  // avoid the DNS lookup
  if (DownloadAccessList.alwaysAuthorized()) {
    return true;
  }

  // parse url
  std::string protocol, hostname, path, ip;
  int port = 1;
  if (BzfNetwork::parseURL(url, protocol, hostname, port, path) &&
      ((protocol == "http") || (protocol == "ftp")) &&
      (port >= 1) && (port <= 65535)) {
    setHudMessage("Access DNS check...");
    Address address(hostname); // get the address  (BLOCKING)
    ip = address.getDotNotation();
    setHudMessage("");
  }

  // make the list of strings to check
  std::vector<std::string> nameAndIp;
  if (hostname.size() > 0) {
    nameAndIp.push_back(hostname);
  }
  if (ip.size() > 0) {
    nameAndIp.push_back(ip);
  }

  // check and print error if not authorized
  if (!DownloadAccessList.authorized(nameAndIp)) {
    std::string msg = ColorStrings[RedColor];
    msg += "local server denial: ";
    msg += ColorStrings[GreyColor];
    msg += url;
    addMessage(NULL, msg);
    return false;
  }

  return true;
}

static void setHudMessage(const std::string& msg)
{
  HUDDialogStack::get()->setFailedMessage(msg.c_str());
  drawFrame(0.0f);
  return;
}

/******************************************************************************/
#else // ! HAVE_CURL
/******************************************************************************/

void Downloads::doDownloads()
{
  bool needWarning = false;
  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, true);

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {
      needWarning = true;
      // one time warning
      std::string msg = ColorStrings[GreyColor];
      msg += "not downloading: " + texUrl;
      addMessage(NULL, msg);
      // avoid future warnings
      MATERIALMGR.setTextureLocal(texUrl, "");
    }
  }

  if (needWarning && BZDB.isTrue("doDownloads")) {
    std::string msg = ColorStrings[RedColor];
    msg += "Downloads are not available for clients without libcurl";
    addMessage(NULL, msg);
    msg = ColorStrings[YellowColor];
    msg += "To disable this message, disable [Automatic Downloads] in";
    addMessage(NULL, msg);
    msg = ColorStrings[YellowColor];
    msg += "Options -> Cache Options, or get a client with libcurl";
    addMessage(NULL, msg);
  }

  return;
}

bool Downloads::updateDownloads(bool& /*rebuild*/)
{
  std::string msg = ColorStrings[RedColor];
  msg += "Downloads are not available for clients without libcurl";
  addMessage(NULL, msg);
  return false;
}

void Downloads::removeTextures()
{
  /* FIXME: just a placeholder as this function is declared but only defined for
     HAVE_CURL building */
  return;
}

/******************************************************************************/
#endif // HAVE_CURL
/******************************************************************************/

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>clean it up<commit_after>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "Downloads.h"

/* common implementation headers */
#include "network.h"
#include "Address.h"
#include "AccessList.h"
#include "CacheManager.h"
#include "BzMaterial.h"
#include "URLManager.h"
#include "AnsiCodes.h"
#include "TextureManager.h"

/* local implementation headers */
#include "playing.h"
#include "HUDDialogStack.h"

// FIXME - someone write a better explanation
static const char DownloadContent[] =
  "#\n"
  "# This file controls the access to servers for downloads.\n"
  "# Patterns are attempted in order against both the hostname\n"
  "# and ip. The first matching pattern sets the state. If no\n"
  "# patterns are matched, then the server is authorized. There\n"
  "# are four types of matches:\n"
  "#\n"
  "#   simple globbing (* and ?)\n"
  "#     allow\n"
  "#     deny\n"
  "#\n"
  "#   regular expressions\n"
  "#     allow_regex\n"
  "#     deny_regex\n"
  "#\n"
  "\n"
  "#\n"
  "# To authorize all servers, remove the last 3 lines.\n"
  "#\n"
  "\n"
  "allow *.bzflag.bz\n"
  "allow *.bzflag.org\n"
  "deny *\n";

static AccessList DownloadAccessList("DownloadAccess.txt", DownloadContent);

/******************************************************************************/
#undef HAVE_CURL
#ifdef HAVE_CURL
/******************************************************************************/

// Function Prototypes
static void printAuthNotice();
static bool getFileTime(const std::string& url, time_t& t);
static bool getAndCacheURL(const std::string& url);
static bool authorizedServer(const std::string& url);
static void setHudMessage(const std::string& msg);

void Downloads::doDownloads()
{
  CACHEMGR.loadIndex();
  CACHEMGR.limitCacheSize();

  DownloadAccessList.reload();

  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, false /* ignore referencing */);

  bool authNotice = false;

  const bool doDownloads =	BZDB.isTrue("doDownloads");
  const bool updateDownloads =  BZDB.isTrue("updateDownloads");

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {

      // check access authorization
      if (!authorizedServer(texUrl)) {
        MATERIALMGR.setTextureLocal(texUrl, "");
        authNotice = true;
        continue;
      }

      // use the cache?
      CacheManager::CacheRecord oldrec;
      if (CACHEMGR.findURL(texUrl, oldrec)) {
        time_t filetime = 0;
        if (doDownloads && updateDownloads) {
          getFileTime(texUrl, filetime);
        }
        if (filetime <= oldrec.date) {
          // use the cached file
          MATERIALMGR.setTextureLocal(texUrl, oldrec.name);
          continue;
        }
      }

      // bail here if we can't download
      if (!doDownloads) {
        MATERIALMGR.setTextureLocal(texUrl, "");
        std::string msg = ColorStrings[GreyColor];
        msg += "not downloading: " + texUrl;
        addMessage(NULL, msg);
        continue;
      }

      // download and cache the URL
      if (getAndCacheURL(texUrl)) {
        const std::string localname = CACHEMGR.getLocalName(texUrl);
        MATERIALMGR.setTextureLocal(texUrl, localname);
      } else {
        MATERIALMGR.setTextureLocal(texUrl, "");
      }
    }
  }

  if (authNotice) {
    printAuthNotice();
  }

  CACHEMGR.saveIndex();

  return;
}

bool Downloads::updateDownloads(bool& rebuild)
{
  CACHEMGR.loadIndex();
  CACHEMGR.limitCacheSize();

  DownloadAccessList.reload();

  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, true /* only referenced materials */);

  TextureManager& TEXMGR = TextureManager::instance();

  rebuild = false;
  bool updated = false;
  bool authNotice = false;

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {

      // check access authorization
      if (!authorizedServer(texUrl)) {
        MATERIALMGR.setTextureLocal(texUrl, "");
        authNotice = true;
        continue;
      }

      // use the cache or update?
      CacheManager::CacheRecord oldrec;
      if (CACHEMGR.findURL(texUrl, oldrec)) {
        time_t filetime;
        getFileTime(texUrl, filetime);
        if (filetime <= oldrec.date) {
          // keep using the cached file
          MATERIALMGR.setTextureLocal(texUrl, oldrec.name);
          if (!TEXMGR.isLoaded(oldrec.name)) {
            rebuild = true;
          }
          continue;
        }
      }

      // download the file and update the cache
      if (getAndCacheURL(texUrl)) {
        updated = true;
        const std::string localname = CACHEMGR.getLocalName(texUrl);
        if (!TEXMGR.isLoaded(localname)) {
          rebuild = true;
        } else {
          TEXMGR.reloadTextureImage(localname); // reload with the new image
        }
        MATERIALMGR.setTextureLocal(texUrl, localname); // if it wasn't cached
      }
    }
  }

  if (authNotice) {
    printAuthNotice();
  }

  CACHEMGR.saveIndex();

  return updated;
}

void Downloads::removeTextures()
{
  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, false /* ignore referencing */);

  TextureManager& TEXMGR = TextureManager::instance();

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {
      const std::string& localname = CACHEMGR.getLocalName(texUrl);
      if (TEXMGR.isLoaded(localname)) {
        TEXMGR.removeTexture(localname);
      }
    }
  }

  return;
}

static void printAuthNotice()
{
  std::string msg = ColorStrings[WhiteColor];
  msg += "NOTE: ";
  msg += ColorStrings[GreyColor];
  msg += "download access is controlled by ";
  msg += ColorStrings[YellowColor];
  msg += DownloadAccessList.getFileName();
  addMessage(NULL, msg);
  return;
}

static bool getFileTime(const std::string& url, time_t& t)
{
  setHudMessage("Download DNS check...");

  URLManager& URLMGR = URLManager::instance();
  if (URLMGR.getURLHeader(url)) {
    URLMGR.getFileTime(t);
    return true;
  } else {
    t = 0;
    return false;
  }

  setHudMessage("");
}

static bool getAndCacheURL(const std::string& url)
{
  bool result = false;

  setHudMessage("Download DNS check...");

  URLManager& URLMGR = URLManager::instance();
  URLMGR.setProgressFunc(curlProgressFunc, NULL);

  std::string msg = ColorStrings[GreyColor];
  msg += "downloading: " + url;
  addMessage(NULL, msg);

  void* urlData;
  unsigned int urlSize;

  if (URLMGR.getURL(url, &urlData, urlSize)) {
    time_t filetime;
    URLMGR.getFileTime(filetime);
    // CACHEMGR generates name, usedDate, and key
    CacheManager::CacheRecord rec;
    rec.url = url;
    rec.size = urlSize;
    rec.date = filetime;
    CACHEMGR.addFile(rec, urlData);
    free(urlData);
    result = true;
  }
  else {
    std::string msg = ColorStrings[RedColor] + "* failure *";
    addMessage(NULL, msg);
    result = false;
  }

  URLMGR.setProgressFunc(NULL, NULL);

  setHudMessage("");

  return result;
}

static bool authorizedServer(const std::string& url)
{
  // avoid the DNS lookup
  if (DownloadAccessList.alwaysAuthorized()) {
    return true;
  }

  // parse url
  std::string protocol, hostname, path, ip;
  int port = 1;
  if (BzfNetwork::parseURL(url, protocol, hostname, port, path) &&
      ((protocol == "http") || (protocol == "ftp")) &&
      (port >= 1) && (port <= 65535)) {
    setHudMessage("Access DNS check...");
    Address address(hostname); // get the address  (BLOCKING)
    ip = address.getDotNotation();
    setHudMessage("");
  }

  // make the list of strings to check
  std::vector<std::string> nameAndIp;
  if (hostname.size() > 0) {
    nameAndIp.push_back(hostname);
  }
  if (ip.size() > 0) {
    nameAndIp.push_back(ip);
  }

  // check and print error if not authorized
  if (!DownloadAccessList.authorized(nameAndIp)) {
    std::string msg = ColorStrings[RedColor];
    msg += "local server denial: ";
    msg += ColorStrings[GreyColor];
    msg += url;
    addMessage(NULL, msg);
    return false;
  }

  return true;
}

static void setHudMessage(const std::string& msg)
{
  HUDDialogStack::get()->setFailedMessage(msg.c_str());
  drawFrame(0.0f);
  return;
}

/******************************************************************************/
#else // ! HAVE_CURL
/******************************************************************************/

void Downloads::doDownloads()
{
  bool needWarning = false;
  BzMaterialManager::TextureSet set;
  BzMaterialManager::TextureSet::iterator set_it;
  MATERIALMGR.makeTextureList(set, false /* ignore referencing */);

  for (set_it = set.begin(); set_it != set.end(); set_it++) {
    const std::string& texUrl = set_it->c_str();
    if (CACHEMGR.isCacheFileType(texUrl)) {
      needWarning = true;
      // one time warning
      std::string msg = ColorStrings[GreyColor];
      msg += "not downloading: " + texUrl;
      addMessage(NULL, msg);
      // avoid future warnings
      MATERIALMGR.setTextureLocal(texUrl, "");
    }
  }

  if (needWarning && BZDB.isTrue("doDownloads")) {
    std::string msg = ColorStrings[RedColor];
    msg += "Downloads are not available for clients without libcurl";
    addMessage(NULL, msg);
    msg = ColorStrings[YellowColor];
    msg += "To disable this message, disable [Automatic Downloads] in";
    addMessage(NULL, msg);
    msg = ColorStrings[YellowColor];
    msg += "Options -> Cache Options, or get a client with libcurl";
    addMessage(NULL, msg);
  }

  return;
}

bool Downloads::updateDownloads(bool& /*rebuild*/)
{
  std::string msg = ColorStrings[RedColor];
  msg += "Downloads are not available for clients without libcurl";
  addMessage(NULL, msg);
  return false;
}

void Downloads::removeTextures()
{
  return;
}

/******************************************************************************/
#endif // HAVE_CURL
/******************************************************************************/

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>