Skip to content

Commit

Permalink
Don't allow UCS-2/4 encoding when set via a config file or the env.
Browse files Browse the repository at this point in the history
This includes using a ConvKey rather than just a string when setting
the encoding.  The ConvKey contans an additional flag that will
indicate if UCS-2/4 is allowed.  To determine is UCS-2/4 is allowed a
new method, retrieve_value, is added to Config that returns additional
information on the value.  UCS-2/4 is only allowed if the Value object
returned from retrieve_value("encoding") has the secure flag set.
  • Loading branch information
kevina committed Sep 21, 2019
1 parent 9e5c5f9 commit 4169e76
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 64 deletions.
11 changes: 11 additions & 0 deletions common/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,16 @@ namespace acommon {
return cur ? cur->value : get_default(ki);
}

PosibErr<Config::Value> Config::retrieve_value(ParmStr key) const
{
RET_ON_ERR_SET(keyinfo(key), const KeyInfo *, ki);
if (ki->type == KeyInfoList) return make_err(key_not_string, ki->name);

const Entry * cur = lookup(ki->name);

return cur ? Value(cur->value,cur->secure) : Value(get_default(ki), true);
}

PosibErr<String> Config::retrieve_any(ParmStr key) const
{
RET_ON_ERR_SET(keyinfo(key), const KeyInfo *, ki);
Expand Down Expand Up @@ -795,6 +805,7 @@ namespace acommon {
Entry * entry = new Entry;
entry->key = key;
entry->value = value;
entry->secure = true;
return set(entry);
}

Expand Down
15 changes: 12 additions & 3 deletions common/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,10 @@ namespace acommon {
unsigned line_num;
Action action;
bool need_conv;
bool secure; // if the value was set in a secure content
short place_holder;
Entry() : line_num(0), action(NoOp),
need_conv(false), place_holder(-1) {}
need_conv(false), secure(false), place_holder(-1) {}
};

private:
Expand Down Expand Up @@ -164,8 +165,8 @@ namespace acommon {
PosibErr<const ConfigModule *> (* load_filter_hook)(Config * config, ParmStr value);
Notifier * filter_mode_notifier;

Vector<ConfigModule> filter_modules;
Vector<Cacheable *> filter_modules_ptrs;
Vector<ConfigModule> filter_modules;
Vector<Cacheable *> filter_modules_ptrs;

Config(ParmStr name,
const KeyInfo * mainbegin,
Expand Down Expand Up @@ -207,6 +208,14 @@ namespace acommon {

PosibErr<String> retrieve(ParmStr key) const;

struct Value {
String val;
bool secure;
Value() {}
Value(const String & v, bool s = false) : val(v), secure(s) {}
};
PosibErr<Value> retrieve_value(ParmStr key) const;

// will also retrieve a list, with one value per line
PosibErr<String> retrieve_any(ParmStr key) const;

Expand Down
99 changes: 61 additions & 38 deletions common/convert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,7 @@ namespace acommon {
snprintf(m, 70, _("The Unicode code point U+%04X is unsupported."), in->chr);
return make_err(invalid_string, orig, m);
}

out.append(&c, sizeof(Chr));
}
return no_err;
Expand Down Expand Up @@ -972,18 +973,18 @@ namespace acommon {
}

PosibErr<Convert *> internal_new_convert(const Config & c,
ParmString in,
ParmString out,
ConvKey in,
ConvKey out,
bool if_needed,
Normalize norm)
{
String in_s;
in = fix_encoding_str(in, in_s);
in.val = fix_encoding_str(in.val, in_s);

String out_s;
out = fix_encoding_str(out, out_s);
out.val = fix_encoding_str(out.val, out_s);

if (if_needed && in == out) return 0;
if (if_needed && in.val == out.val) return 0;

StackPtr<Convert> conv(new Convert);
switch (norm) {
Expand All @@ -997,57 +998,79 @@ namespace acommon {
return conv.release();
}

PosibErr<Decode *> Decode::get_new(const String & key, const Config * c)
PosibErr<Decode *> Decode::get_new(const ConvKey & k, const Config * c)
{
StackPtr<Decode> ptr;
if (key == "iso-8859-1")
if (k.val == "iso-8859-1") {
ptr.reset(new DecodeDirect<Uni8>);
else if (key == "ucs-2")
ptr.reset(new DecodeDirect<Uni16>);
else if (key == "ucs-4")
ptr.reset(new DecodeDirect<Uni32>);
else if (key == "utf-8")
} else if (k.val == "ucs-2") {
if (k.allow_ucs)
ptr.reset(new DecodeDirect<Uni16>);
else
return make_err(encoding_not_supported, k.val);
} else if (k.val == "ucs-4") {
if (k.allow_ucs)
ptr.reset(new DecodeDirect<Uni32>);
else
return make_err(encoding_not_supported, k.val);
} else if (k.val == "utf-8") {
ptr.reset(new DecodeUtf8);
else
} else {
ptr.reset(new DecodeLookup);
RET_ON_ERR(ptr->init(key, *c));
ptr->key = key;
}
RET_ON_ERR(ptr->init(k.val, *c));
ptr->key = k.val;
return ptr.release();
}

PosibErr<Encode *> Encode::get_new(const String & key, const Config * c)
PosibErr<Encode *> Encode::get_new(const ConvKey & k, const Config * c)
{
StackPtr<Encode> ptr;
if (key == "iso-8859-1")
if (k.val == "iso-8859-1") {
ptr.reset(new EncodeDirect<Uni8>);
else if (key == "ucs-2")
ptr.reset(new EncodeDirect<Uni16>);
else if (key == "ucs-4")
ptr.reset(new EncodeDirect<Uni32>);
else if (key == "utf-8")
} else if (k.val == "ucs-2" && k.allow_ucs) {
if (k.allow_ucs)
ptr.reset(new EncodeDirect<Uni16>);
else
return make_err(encoding_not_supported, k.val);
} else if (k.val == "ucs-4" && k.allow_ucs) {
if (k.allow_ucs)
ptr.reset(new EncodeDirect<Uni32>);
else
return make_err(encoding_not_supported, k.val);
} else if (k.val == "utf-8") {
ptr.reset(new EncodeUtf8);
else
} else {
ptr.reset(new EncodeLookup);
RET_ON_ERR(ptr->init(key, *c));
ptr->key = key;
}
RET_ON_ERR(ptr->init(k.val, *c));
ptr->key = k.val;
return ptr.release();
}

Convert::~Convert() {}

PosibErr<void> Convert::init(const Config & c, ParmStr in, ParmStr out)
PosibErr<void> Convert::init(const Config & c, const ConvKey & in, const ConvKey & out)
{
RET_ON_ERR(setup(decode_c, &decode_cache, &c, in));
decode_ = decode_c.get();
RET_ON_ERR(setup(encode_c, &encode_cache, &c, out));
encode_ = encode_c.get();

conv_ = 0;
if (in == out) {
if (in == "ucs-2") {
conv_ = new ConvDirect<Uni16>;
} else if (in == "ucs-4") {
conv_ = new ConvDirect<Uni32>;
if (in.val == out.val) {
if (in.val == "ucs-2") {
if (in.allow_ucs) {
conv_ = new ConvDirect<Uni16>;
} else {
return make_err(encoding_not_supported, in.val);
}
} else if (in.val == "ucs-4") {
if (in.allow_ucs) {
conv_ = new ConvDirect<Uni32>;
} else {
return make_err(encoding_not_supported, in.val);
}
} else {
conv_ = new ConvDirect<char>;
}
Expand All @@ -1060,33 +1083,33 @@ namespace acommon {
}


PosibErr<void> Convert::init_norm_from(const Config & c, ParmStr in, ParmStr out)
PosibErr<void> Convert::init_norm_from(const Config & c, const ConvKey & in, const ConvKey & out)
{
if (!c.retrieve_bool("normalize") && !c.retrieve_bool("norm-required"))
return init(c,in,out);

RET_ON_ERR(setup(norm_tables_, &norm_tables_cache, &c, out));
RET_ON_ERR(setup(norm_tables_, &norm_tables_cache, &c, out.val));

RET_ON_ERR(setup(decode_c, &decode_cache, &c, in));
decode_ = decode_c.get();

if (c.retrieve_bool("norm-strict")) {
encode_s = new EncodeNormLookup(norm_tables_->strict);
encode_ = encode_s;
encode_->key = out;
encode_->key = out.val;
encode_->key += ":strict";
} else {
encode_s = new EncodeNormLookup(norm_tables_->internal);
encode_ = encode_s;
encode_->key = out;
encode_->key = out.val;
encode_->key += ":internal";
}
conv_ = 0;

return no_err;
}

PosibErr<void> Convert::init_norm_to(const Config & c, ParmStr in, ParmStr out)
PosibErr<void> Convert::init_norm_to(const Config & c, const ConvKey & in, const ConvKey & out)
{
String norm_form = c.retrieve("norm-form");
if ((!c.retrieve_bool("normalize") || norm_form == "none")
Expand All @@ -1095,7 +1118,7 @@ namespace acommon {
if (norm_form == "none" && c.retrieve_bool("norm-required"))
norm_form = "nfc";

RET_ON_ERR(setup(norm_tables_, &norm_tables_cache, &c, in));
RET_ON_ERR(setup(norm_tables_, &norm_tables_cache, &c, in.val));

RET_ON_ERR(setup(encode_c, &encode_cache, &c, out));
encode_ = encode_c.get();
Expand All @@ -1107,7 +1130,7 @@ namespace acommon {

decode_s = new DecodeNormLookup(i->ptr);
decode_ = decode_s;
decode_->key = in;
decode_->key = in.val;
decode_->key += ':';
decode_->key += i->name;

Expand Down
39 changes: 24 additions & 15 deletions common/convert.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,21 @@ namespace acommon {
class OStream;
class Config;

struct ConvKey {
ParmString val;
bool allow_ucs;
ConvKey() : val(), allow_ucs() {}
template <typename T>
ConvKey(const T & v, bool a = false) : val(v), allow_ucs(a) {}
};

struct ConvBase : public Cacheable {
typedef const Config CacheConfig;
typedef const char * CacheKey;
typedef ConvKey CacheKey;
String key;
int type_width; // type width in bytes
bool cache_key_eq(const char * l) const {return key == l;}
bool is_ucs() const {return type_width != 1;}
bool cache_key_eq(CacheKey k) const {return k.allow_ucs ? key == k.val : key == k.val && !is_ucs();}
ConvBase() : type_width(1) {}
private:
ConvBase(const ConvBase &);
Expand All @@ -41,7 +50,7 @@ namespace acommon {
FilterCharVector & out) const = 0;
virtual PosibErr<void> decode_ec(const char * in, int size,
FilterCharVector & out, ParmStr orig) const = 0;
static PosibErr<Decode *> get_new(const String &, const Config *);
static PosibErr<Decode *> get_new(const ConvKey &, const Config *);
virtual ~Decode() {}
};
struct Encode : public ConvBase {
Expand All @@ -55,7 +64,7 @@ namespace acommon {
// may convert inplace
virtual bool encode(FilterChar * & in, FilterChar * & stop,
FilterCharVector & buf) const {return false;}
static PosibErr<Encode *> get_new(const String &, const Config *);
static PosibErr<Encode *> get_new(const ConvKey &, const Config *);
virtual ~Encode() {}
};
struct DirectConv { // convert directly from in_code to out_code.
Expand Down Expand Up @@ -124,9 +133,9 @@ namespace acommon {
// this class in any way.
Filter filter;

PosibErr<void> init(const Config &, ParmStr in, ParmStr out);
PosibErr<void> init_norm_to(const Config &, ParmStr in, ParmStr out);
PosibErr<void> init_norm_from(const Config &, ParmStr in, ParmStr out);
PosibErr<void> init(const Config &, const ConvKey & in, const ConvKey & out);
PosibErr<void> init_norm_to(const Config &, const ConvKey & in, const ConvKey & out);
PosibErr<void> init_norm_from(const Config &, const ConvKey & in, const ConvKey & out);

const char * in_code() const {return decode_->key.c_str();}
const char * out_code() const {return encode_->key.c_str();}
Expand Down Expand Up @@ -217,19 +226,19 @@ namespace acommon {
enum Normalize {NormNone, NormFrom, NormTo};

PosibErr<Convert *> internal_new_convert(const Config & c,
ParmString in, ParmString out,
ConvKey in, ConvKey out,
bool if_needed,
Normalize n);

static inline PosibErr<Convert *> new_convert(const Config & c,
ParmStr in, ParmStr out,
const ConvKey & in, const ConvKey & out,
Normalize n)
{
return internal_new_convert(c,in,out,false,n);
}

static inline PosibErr<Convert *> new_convert_if_needed(const Config & c,
ParmStr in, ParmStr out,
const ConvKey & in, const ConvKey & out,
Normalize n)
{
return internal_new_convert(c,in,out,true,n);
Expand All @@ -239,7 +248,7 @@ namespace acommon {
Convert * ptr;
ConvObj(Convert * c = 0) : ptr(c) {}
~ConvObj() {delete ptr;}
PosibErr<void> setup(const Config & c, ParmStr from, ParmStr to, Normalize norm)
PosibErr<void> setup(const Config & c, const ConvKey & from, const ConvKey & to, Normalize norm)
{
delete ptr;
ptr = 0;
Expand All @@ -263,7 +272,7 @@ namespace acommon {
ConvP(const ConvObj & c) : conv(c.ptr) {}
ConvP(const ConvP & c) : conv(c.conv) {}
void operator=(const ConvP & c) { conv = c.conv; }
PosibErr<void> setup(const Config & c, ParmStr from, ParmStr to,
PosibErr<void> setup(const Config & c, const ConvKey & from, const ConvKey & to,
Normalize norm)
{
delete conv;
Expand Down Expand Up @@ -334,7 +343,7 @@ namespace acommon {
{
ConvObj conv_obj;
Conv(Convert * c = 0) : ConvP(c), conv_obj(c) {}
PosibErr<void> setup(const Config & c, ParmStr from, ParmStr to, Normalize norm)
PosibErr<void> setup(const Config & c, const ConvKey & from, const ConvKey & to, Normalize norm)
{
RET_ON_ERR(conv_obj.setup(c,from,to,norm));
conv = conv_obj.ptr;
Expand All @@ -351,7 +360,7 @@ namespace acommon {
ConvECP(const ConvObj & c) : conv(c.ptr) {}
ConvECP(const ConvECP & c) : conv(c.conv) {}
void operator=(const ConvECP & c) { conv = c.conv; }
PosibErr<void> setup(const Config & c, ParmStr from, ParmStr to, Normalize norm)
PosibErr<void> setup(const Config & c, const ConvKey & from, const ConvKey & to, Normalize norm)
{
delete conv;
conv = 0;
Expand Down Expand Up @@ -406,7 +415,7 @@ namespace acommon {
{
ConvObj conv_obj;
ConvEC(Convert * c = 0) : ConvECP(c), conv_obj(c) {}
PosibErr<void> setup(const Config & c, ParmStr from, ParmStr to, Normalize norm)
PosibErr<void> setup(const Config & c, const ConvKey & from, const ConvKey & to, Normalize norm)
{
RET_ON_ERR(conv_obj.setup(c,from,to,norm));
conv = conv_obj.ptr;
Expand Down
2 changes: 1 addition & 1 deletion modules/filter/email.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ namespace {
{
name_ = "email-filter";
order_num_ = 0.85;
is_quote_char.conv.setup(*opts, "utf-8", "ucs-4", NormNone);
is_quote_char.conv.setup(*opts, "utf-8", ConvKey("ucs-4", true), NormNone);
RET_ON_ERR(opts->retrieve_list("f-email-quote", &is_quote_char));
margin = opts->retrieve_int("f-email-margin");
reset();
Expand Down
Loading

0 comments on commit 4169e76

Please sign in to comment.