Skip to content
Snippets Groups Projects
Commit d087d6dc authored by Tristan Matthews's avatar Tristan Matthews
Browse files

* #13534: account: add proper validation for video codecs

parent b702f9e9
Branches
Tags android/release_395
No related merge requests found
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "video/libav_utils.h" #include "video/libav_utils.h"
#endif #endif
#include "logger.h"
#include "manager.h" #include "manager.h"
#include "dbus/configurationmanager.h" #include "dbus/configurationmanager.h"
...@@ -116,16 +117,76 @@ void Account::loadDefaultCodecs() ...@@ -116,16 +117,76 @@ void Account::loadDefaultCodecs()
setActiveAudioCodecs(result); setActiveAudioCodecs(result);
#ifdef SFL_VIDEO #ifdef SFL_VIDEO
setVideoCodecs(libav_utils::getDefaultCodecs()); // we don't need to validate via setVideoCodecs, since these are defaults
videoCodecList_ = libav_utils::getDefaultCodecs();
#endif #endif
} }
#ifdef SFL_VIDEO
namespace {
bool isPositiveInteger(const string &s)
{
string::const_iterator it = s.begin();
while (it != s.end() and std::isdigit(*it))
++it;
return not s.empty() and it == s.end();
}
bool isBoolean(const string &s)
{
return s == "true" or s == "false";
}
template <typename Predicate>
bool isFieldValid(const map<string, string> &codec, const char *field, Predicate p)
{
map<string, string>::const_iterator key(codec.find(field));
return key != codec.end() and p(key->second);
}
bool isCodecValid(const map<string, string> &codec, const vector<map<string, string> > &defaults)
{
map<string, string>::const_iterator name(codec.find(Account::VIDEO_CODEC_NAME));
if (name == codec.end()) {
ERROR("Field \"name\" missing in codec specification");
return false;
}
// check that it's in the list of valid codecs and that it has all the required fields
for (vector<map<string, string> >::const_iterator i = defaults.begin(); i != defaults.end(); ++i) {
map<string, string>::const_iterator defaultName = i->find(Account::VIDEO_CODEC_NAME);
if (defaultName->second == name->second) {
return isFieldValid(codec, Account::VIDEO_CODEC_BITRATE, isPositiveInteger)
and isFieldValid(codec, Account::VIDEO_CODEC_ENABLED, isBoolean);
}
}
ERROR("Codec %s not supported", name->second.c_str());
return false;
}
bool isCodecListValid(const vector<map<string, string> > &list)
{
const vector<map<string, string> > defaults(libav_utils::getDefaultCodecs());
if (list.size() != defaults.size()) {
ERROR("New codec list has a different length than the list of supported codecs");
return false;
}
// make sure that all codecs are present
for (vector<map<string, string> >::const_iterator i = list.begin();
i != list.end(); ++i) {
if (not isCodecValid(*i, defaults))
return false;
}
return true;
}
}
#endif
void Account::setVideoCodecs(const vector<map<string, string> > &list) void Account::setVideoCodecs(const vector<map<string, string> > &list)
{ {
#ifdef SFL_VIDEO #ifdef SFL_VIDEO
// first clear the previously stored codecs if (isCodecListValid(list))
videoCodecList_.clear();
// FIXME: do real validation here
videoCodecList_ = list; videoCodecList_ = list;
#else #else
(void) list; (void) list;
......
...@@ -184,6 +184,8 @@ class Account : public Serializable { ...@@ -184,6 +184,8 @@ class Account : public Serializable {
} }
static const char * const VIDEO_CODEC_ENABLED; static const char * const VIDEO_CODEC_ENABLED;
static const char * const VIDEO_CODEC_NAME;
static const char * const VIDEO_CODEC_BITRATE;
private: private:
NON_COPYABLE(Account); NON_COPYABLE(Account);
...@@ -197,8 +199,6 @@ class Account : public Serializable { ...@@ -197,8 +199,6 @@ class Account : public Serializable {
// General configuration keys for accounts // General configuration keys for accounts
static const char * const AUDIO_CODECS_KEY; static const char * const AUDIO_CODECS_KEY;
static const char * const VIDEO_CODECS_KEY; static const char * const VIDEO_CODECS_KEY;
static const char * const VIDEO_CODEC_NAME;
static const char * const VIDEO_CODEC_BITRATE;
static const char * const RINGTONE_PATH_KEY; static const char * const RINGTONE_PATH_KEY;
static const char * const RINGTONE_ENABLED_KEY; static const char * const RINGTONE_ENABLED_KEY;
static const char * const DISPLAY_NAME_KEY; static const char * const DISPLAY_NAME_KEY;
......
...@@ -317,7 +317,7 @@ void SIPAccount::unserialize(const Conf::MappingNode &mapNode) ...@@ -317,7 +317,7 @@ void SIPAccount::unserialize(const Conf::MappingNode &mapNode)
if (seq->empty()) { if (seq->empty()) {
// Video codecs are an empty list // Video codecs are an empty list
WARN("Loading default video codecs"); WARN("Loading default video codecs");
setVideoCodecs(libav_utils::getDefaultCodecs()); videoCodecList_ = libav_utils::getDefaultCodecs();
} else { } else {
vector<map<string, string> > videoCodecDetails; vector<map<string, string> > videoCodecDetails;
for (Sequence::iterator it = seq->begin(); it != seq->end(); ++it) { for (Sequence::iterator it = seq->begin(); it != seq->end(); ++it) {
...@@ -328,13 +328,14 @@ void SIPAccount::unserialize(const Conf::MappingNode &mapNode) ...@@ -328,13 +328,14 @@ void SIPAccount::unserialize(const Conf::MappingNode &mapNode)
codec->getValue(VIDEO_CODEC_ENABLED, &codecMap[VIDEO_CODEC_ENABLED]); codec->getValue(VIDEO_CODEC_ENABLED, &codecMap[VIDEO_CODEC_ENABLED]);
videoCodecDetails.push_back(codecMap); videoCodecDetails.push_back(codecMap);
} }
// these must be validated
setVideoCodecs(videoCodecDetails); setVideoCodecs(videoCodecDetails);
} }
} else { } else {
// either this is an older config file which had videoCodecs as a scalar node, // either this is an older config file which had videoCodecs as a scalar node,
// or it had no video codecs at all // or it had no video codecs at all
WARN("Loading default video codecs"); WARN("Loading default video codecs");
setVideoCodecs(libav_utils::getDefaultCodecs()); videoCodecList_ = libav_utils::getDefaultCodecs();
} }
#endif #endif
......
...@@ -366,10 +366,12 @@ bitrate_edited_cb(GtkCellRenderer *renderer UNUSED, gchar *path, gchar *new_text ...@@ -366,10 +366,12 @@ bitrate_edited_cb(GtkCellRenderer *renderer UNUSED, gchar *path, gchar *new_text
// Get active value and name at iteration // Get active value and name at iteration
const gint base = 10; const gint base = 10;
gchar *endptr; gchar *endptr;
const unsigned long long val = strtoull(new_text, &endptr, base); const long long val = strtoll(new_text, &endptr, base);
/* Ignore if it's not a number */ /* Ignore if it's not a number */
if (*endptr != '\0') { if (*endptr != '\0') {
WARN("Ignoring characters %s\n", val, endptr); WARN("Ignoring characters %s\n", val, endptr);
} else if (val < 0) {
WARN("Ignoring negative bitrate value");
} else { } else {
// Get path of edited codec // Get path of edited codec
GtkTreePath *tree_path = gtk_tree_path_new_from_string(path); GtkTreePath *tree_path = gtk_tree_path_new_from_string(path);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment