summaryrefslogtreecommitdiffstats
path: root/core/m_option.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/m_option.c')
-rw-r--r--core/m_option.c274
1 files changed, 26 insertions, 248 deletions
diff --git a/core/m_option.c b/core/m_option.c
index 02258416ec..41916befeb 100644
--- a/core/m_option.c
+++ b/core/m_option.c
@@ -1776,8 +1776,6 @@ const m_option_type_t m_option_type_rel_time = {
//// Objects (i.e. filters, etc) settings
-#include "core/m_struct.h"
-
#undef VAL
#define VAL(x) (*(m_obj_settings_t **)(x))
@@ -1963,7 +1961,7 @@ static void copy_obj_settings_list(const m_option_t *opt, void *dst,
// option names/values are correct. Try to determine whether an option
// without '=' sets a flag, or whether it's a positional argument.
static int get_obj_param(bstr opt_name, bstr obj_name, struct m_config *config,
- bstr name, bstr val, int *nold,
+ bstr name, bstr val, int flags, int *nold,
bstr *out_name, bstr *out_val)
{
int r;
@@ -1975,7 +1973,7 @@ static int get_obj_param(bstr opt_name, bstr obj_name, struct m_config *config,
// If it's just "name", and the associated option exists and is a flag,
// don't accept it as positional argument.
if (val.start || m_config_option_requires_param(config, name) == 0) {
- r = m_config_set_option(config, name, val);
+ r = m_config_set_option_ext(config, name, val, flags);
if (r < 0) {
if (r == M_OPT_UNKNOWN) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
@@ -2007,7 +2005,7 @@ static int get_obj_param(bstr opt_name, bstr obj_name, struct m_config *config,
BSTR_P(opt_name), BSTR_P(obj_name), *nold, *nold);
return M_OPT_OUT_OF_RANGE;
}
- r = m_config_set_option(config, bstr0(opt), val);
+ r = m_config_set_option_ext(config, bstr0(opt), val, flags);
if (r < 0) {
if (r > M_OPT_EXIT)
mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %.*s: "
@@ -2023,11 +2021,14 @@ static int get_obj_param(bstr opt_name, bstr obj_name, struct m_config *config,
}
// Consider -vf a=b:c:d. This parses "b:c:d" into name/value pairs, stored as
-// linear array in *_ret. In particular, desc contains what options a the
+// linear array in *_ret. In particular, config contains what options a the
// object takes, and verifies the option values as well.
-static int get_obj_params(struct bstr opt_name, struct bstr name,
- struct bstr *pstr, struct m_obj_desc *desc,
- char ***ret)
+// If config is NULL, all parameters are accepted without checking.
+// _ret set to NULL can be used for checking-only.
+// flags can contain any M_SETOPT_* flag.
+int m_obj_parse_sub_config(struct bstr opt_name, struct bstr name,
+ struct bstr *pstr, struct m_config *config,
+ int flags, char ***ret)
{
int nold = 0;
char **args = NULL;
@@ -2040,8 +2041,6 @@ static int get_obj_params(struct bstr opt_name, struct bstr name,
num_args++;
}
- struct m_config *config = m_config_from_obj_desc(NULL, desc);
-
while (pstr->len > 0) {
bstr fname, fval;
r = split_subconf(opt_name, pstr, &fname, &fval);
@@ -2049,7 +2048,7 @@ static int get_obj_params(struct bstr opt_name, struct bstr name,
goto exit;
if (bstr_equals0(fname, "help"))
goto print_help;
- r = get_obj_param(opt_name, name, config, fname, fval, &nold,
+ r = get_obj_param(opt_name, name, config, fname, fval, flags, &nold,
&fname, &fval);
if (r < 0)
goto exit;
@@ -2088,7 +2087,6 @@ print_help: ;
exit:
free_str_list(&args);
- talloc_free(config);
return r;
}
@@ -2121,26 +2119,22 @@ static int parse_obj_settings(struct bstr opt, struct bstr *pstr,
if (bstr_eatstart0(pstr, "=") || bstr_eatstart0(pstr, ":"))
has_param = true;
- if (!m_obj_list_find(&desc, list, str)) {
+ bool legacy = false;
+ bool skip = false;
+ if (m_obj_list_find(&desc, list, str)) {
+ legacy = !desc.priv_size && list->legacy_hacks;
+ } else {
if (!list->allow_unknown_entries) {
mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %.*s: %.*s doesn't exist.\n",
BSTR_P(opt), BSTR_P(str));
return M_OPT_INVALID;
}
desc = (struct m_obj_desc){0};
- }
-
- if (desc.init_options && desc.options && _ret) {
- bstr s = bstr0(desc.init_options);
- r = get_obj_params(opt, str, &s, &desc, &plist);
- if (r < 0 || s.len > 0) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Internal error: preset broken\n");
- return r;
- }
+ skip = true;
}
if (has_param) {
- if (!desc.options && list->legacy_hacks) {
+ if (legacy) {
// Should perhaps be parsed as escape-able string. But this is a
// compatibility path, so it's not worth the trouble.
int next = bstrcspn(*pstr, ",");
@@ -2158,7 +2152,13 @@ static int parse_obj_settings(struct bstr opt, struct bstr *pstr,
plist[1] = bstrto0(NULL, param);
}
} else {
- r = get_obj_params(opt, str, pstr, &desc, _ret ? &plist : NULL);
+ struct m_config *config = NULL;
+ if (!skip)
+ config = m_config_from_obj_desc(NULL, &desc);
+ r = m_obj_parse_sub_config(opt, str, pstr, config,
+ M_SETOPT_CHECK_ONLY,
+ _ret ? &plist : NULL);
+ talloc_free(config);
if (r < 0)
return r;
}
@@ -2379,7 +2379,7 @@ static int parse_obj_settings_list(const m_option_t *opt, struct bstr name,
int found = obj_settings_find_by_content(list, &res[n]);
if (found < 0) {
mp_msg(MSGT_CFGPARSER, MSGL_WARN,
- "Option %.*s: Item bot found\n", BSTR_P(name));
+ "Option %.*s: Item not found\n", BSTR_P(name));
} else {
obj_settings_list_del_at(&list, found);
}
@@ -2405,225 +2405,3 @@ const m_option_type_t m_option_type_obj_settings_list = {
.copy = copy_obj_settings_list,
.free = free_obj_settings_list,
};
-
-
-/* Replace escape sequences in an URL (or a part of an URL) */
-/* works like strcpy(), but without return argument,
- except that outbuf == inbuf is allowed */
-static void url_unescape_string(char *outbuf, const char *inbuf)
-{
- unsigned char c,c1,c2;
- int i,len=strlen(inbuf);
- for (i=0;i<len;i++) {
- c = inbuf[i];
- if (c == '%' && i<len-2) { //must have 2 more chars
- c1 = toupper(inbuf[i+1]); // we need uppercase characters
- c2 = toupper(inbuf[i+2]);
- if (((c1>='0' && c1<='9') || (c1>='A' && c1<='F')) &&
- ((c2>='0' && c2<='9') || (c2>='A' && c2<='F')) )
- {
- if (c1>='0' && c1<='9')
- c1-='0';
- else
- c1-='A'-10;
- if (c2>='0' && c2<='9')
- c2-='0';
- else
- c2-='A'-10;
- c = (c1<<4) + c2;
- i=i+2; //only skip next 2 chars if valid esc
- }
- }
- *outbuf++ = c;
- }
- *outbuf++='\0'; //add nullterm to string
-}
-
-static int parse_custom_url(const m_option_t *opt, struct bstr name,
- struct bstr url, void *dst)
-{
- int r;
- m_struct_t *desc = opt->priv;
-
- if (!desc) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %.*s: Custom URL needs "
- "a pointer to a m_struct_t in the priv field.\n", BSTR_P(name));
- return M_OPT_PARSER_ERR;
- }
-
- // extract the protocol
- int idx = bstr_find0(url, "://");
- if (idx < 0) {
- // Filename only
- if (m_option_list_find(desc->fields, "filename")) {
- m_struct_set(desc, dst, "filename", url);
- return 1;
- }
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Option %.*s: URL doesn't have a valid protocol!\n",
- BSTR_P(name));
- return M_OPT_INVALID;
- }
- struct bstr ptr1 = bstr_cut(url, idx + 3);
- if (m_option_list_find(desc->fields, "string")) {
- if (ptr1.len > 0) {
- m_struct_set(desc, dst, "string", ptr1);
- return 1;
- }
- }
- if (dst && m_option_list_find(desc->fields, "protocol")) {
- r = m_struct_set(desc, dst, "protocol", bstr_splice(url, 0, idx));
- if (r < 0) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Option %.*s: Error while setting protocol.\n",
- BSTR_P(name));
- return r;
- }
- }
-
- // check if a username:password is given
- idx = bstrchr(ptr1, '/');
- if (idx < 0)
- idx = ptr1.len;
- struct bstr hostpart = bstr_splice(ptr1, 0, idx);
- struct bstr path = bstr_cut(ptr1, idx);
- idx = bstrchr(hostpart, '@');
- if (idx >= 0) {
- struct bstr userpass = bstr_splice(hostpart, 0, idx);
- hostpart = bstr_cut(hostpart, idx + 1);
- // We got something, at least a username...
- if (!m_option_list_find(desc->fields, "username")) {
- mp_msg(MSGT_CFGPARSER, MSGL_WARN,
- "Option %.*s: This URL doesn't have a username part.\n",
- BSTR_P(name));
- // skip
- } else {
- idx = bstrchr(userpass, ':');
- if (idx >= 0) {
- // We also have a password
- if (!m_option_list_find(desc->fields, "password")) {
- mp_msg(MSGT_CFGPARSER, MSGL_WARN,
- "Option %.*s: This URL doesn't have a password part.\n",
- BSTR_P(name));
- // skip
- } else { // Username and password
- if (dst) {
- r = m_struct_set(desc, dst, "username",
- bstr_splice(userpass, 0, idx));
- if (r < 0) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Option %.*s: Error while setting username.\n",
- BSTR_P(name));
- return r;
- }
- r = m_struct_set(desc, dst, "password",
- bstr_splice(userpass, idx+1,
- userpass.len));
- if (r < 0) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Option %.*s: Error while setting password.\n",
- BSTR_P(name));
- return r;
- }
- }
- }
- } else { // User name only
- r = m_struct_set(desc, dst, "username", userpass);
- if (r < 0) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Option %.*s: Error while setting username.\n",
- BSTR_P(name));
- return r;
- }
- }
- }
- }
-
- // Before looking for a port number check if we have an IPv6 type
- // numeric address.
- // In an IPv6 URL the numeric address should be inside square braces.
- int idx1 = bstrchr(hostpart, '[');
- int idx2 = bstrchr(hostpart, ']');
- struct bstr portstr = hostpart;
- bool v6addr = false;
- if (idx1 >= 0 && idx2 >= 0 && idx1 < idx2) {
- // we have an IPv6 numeric address
- portstr = bstr_cut(hostpart, idx2);
- hostpart = bstr_splice(hostpart, idx1 + 1, idx2);
- v6addr = true;
- }
-
- idx = bstrchr(portstr, ':');
- if (idx >= 0) {
- if (!v6addr)
- hostpart = bstr_splice(hostpart, 0, idx);
- // We have an URL beginning like http://www.hostname.com:1212
- // Get the port number
- if (!m_option_list_find(desc->fields, "port")) {
- mp_msg(MSGT_CFGPARSER, MSGL_WARN,
- "Option %.*s: This URL doesn't have a port part.\n",
- BSTR_P(name));
- // skip
- } else {
- if (dst) {
- int p = bstrtoll(bstr_cut(portstr, idx + 1), NULL, 0);
- char tmp[100];
- snprintf(tmp, 99, "%d", p);
- r = m_struct_set(desc, dst, "port", bstr0(tmp));
- if (r < 0) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Option %.*s: Error while setting port.\n",
- BSTR_P(name));
- return r;
- }
- }
- }
- }
- // Get the hostname
- if (hostpart.len > 0) {
- if (!m_option_list_find(desc->fields, "hostname")) {
- mp_msg(MSGT_CFGPARSER, MSGL_WARN,
- "Option %.*s: This URL doesn't have a hostname part.\n",
- BSTR_P(name));
- // skip
- } else {
- r = m_struct_set(desc, dst, "hostname", hostpart);
- if (r < 0) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Option %.*s: Error while setting hostname.\n",
- BSTR_P(name));
- return r;
- }
- }
- }
- // Look if a path is given
- if (path.len > 1) { // not just "/"
- // copy the path/filename in the URL container
- if (!m_option_list_find(desc->fields, "filename")) {
- mp_msg(MSGT_CFGPARSER, MSGL_WARN,
- "Option %.*s: This URL doesn't have a filename part.\n",
- BSTR_P(name));
- // skip
- } else {
- if (dst) {
- char *fname = bstrdup0(NULL, bstr_cut(path, 1));
- url_unescape_string(fname, fname);
- r = m_struct_set(desc, dst, "filename", bstr0(fname));
- talloc_free(fname);
- if (r < 0) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "Option %.*s: Error while setting filename.\n",
- BSTR_P(name));
- return r;
- }
- }
- }
- }
- return 1;
-}
-
-/// TODO : Write the other needed funcs for 'normal' options
-const m_option_type_t m_option_type_custom_url = {
- .name = "Custom URL",
- .parse = parse_custom_url,
-};