diff --git a/src/ssb.db.c b/src/ssb.db.c index 36039548..867cd521 100644 --- a/src/ssb.db.c +++ b/src/ssb.db.c @@ -2046,6 +2046,10 @@ bool tf_ssb_db_get_global_setting_bool(sqlite3* db, const char* name, bool* out_ { tf_printf("prepare failed: %s\n", sqlite3_errmsg(db)); } + if (!result) + { + *out_value = tf_util_get_default_global_setting_bool(name); + } return result; } @@ -2069,6 +2073,10 @@ bool tf_ssb_db_get_global_setting_int64(sqlite3* db, const char* name, int64_t* { tf_printf("prepare failed: %s\n", sqlite3_errmsg(db)); } + if (!result) + { + *out_value = tf_util_get_default_global_setting_int(name); + } return result; } @@ -2092,6 +2100,10 @@ bool tf_ssb_db_get_global_setting_string(sqlite3* db, const char* name, char* ou { tf_printf("prepare failed: %s\n", sqlite3_errmsg(db)); } + if (!result) + { + snprintf(out_value, size, "%s", tf_util_get_default_global_setting_string(name)); + } return result; } diff --git a/src/util.js.c b/src/util.js.c index 3d03ee60..5dac6d0b 100644 --- a/src/util.js.c +++ b/src/util.js.c @@ -20,6 +20,16 @@ #include #endif +#if defined(__APPLE__) +#include +#endif + +#if defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IPHONE) +#define TF_IS_MOBILE 1 +#else +#define TF_IS_MOBILE 0 +#endif + static JSValue _util_utf8_encode(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) { size_t length = 0; @@ -304,73 +314,139 @@ static JSValue _util_parseHttpResponse(JSContext* context, JSValueConst this_val return result; } -#if defined(__APPLE__) -#include -#endif - -static bool _is_mobile() +typedef enum _value_kind_t { -#if defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IPHONE) - return true; -#else - return false; -#endif + k_kind_bool, + k_kind_int, + k_kind_string, +} value_kind_t; + +static const char* k_kind_name[] = { + [k_kind_bool] = "bool", + [k_kind_int] = "int", + [k_kind_string] = "string", +}; + +typedef struct _setting_value_t +{ + value_kind_t kind; + union + { + bool bool_value; + int int_value; + const char* string_value; + }; +} setting_value_t; + +typedef struct _setting_t +{ + const char* name; + const char* type; + const char* description; + setting_value_t default_value; +} setting_t; + +static const setting_t k_settings[] = { + { .name = "code_of_conduct", .type = "textarea", .description = "Code of conduct presented at sign-in.", .default_value = { .kind = k_kind_string, .string_value = NULL } }, + { .name = "blob_fetch_age_seconds", + .type = "integer", + .description = "Only blobs mentioned more recently than this age will be automatically fetched.", + .default_value = { .kind = k_kind_int, .int_value = TF_IS_MOBILE ? (int)(0.5f * 365 * 24 * 60 * 60) : -1 } }, + { .name = "blob_expire_age_seconds", + .type = "integer", + .description = "Blobs older than this will be automatically deleted.", + .default_value = { .kind = k_kind_int, .int_value = TF_IS_MOBILE ? (int)(1.0f * 365 * 24 * 60 * 60) : -1 } }, + { .name = "fetch_hosts", + .type = "string", + .description = "Comma-separated list of host names to which HTTP fetch requests are allowed. None if empty.", + .default_value = { .kind = k_kind_string, .string_value = NULL } }, + { .name = "http_redirect", + .type = "string", + .description = "If connecting by HTTP and HTTPS is configured, Location header prefix (ie, \"http://example.com\")", + .default_value = { .kind = k_kind_string, .string_value = NULL } }, + { .name = "index", .type = "string", .description = "Default path.", .default_value = { .kind = k_kind_string, .string_value = "/~core/ssb/" } }, + { .name = "index_map", + .type = "textarea", + .description = "Mappings from hostname to redirect path, one per line, as in: \"www.tildefriends.net=/~core/index/\"", + .default_value = { .kind = k_kind_string, .string_value = NULL } }, + { .name = "peer_exchange", + .type = "boolean", + .description = "Enable discovery of, sharing of, and connecting to internet peer strangers, including announcing this instance.", + .default_value = { .kind = k_kind_bool, .bool_value = false } }, + { .name = "replicator", .type = "boolean", .description = "Enable message and blob replication.", .default_value = { .kind = k_kind_bool, .bool_value = true } }, + { .name = "room", .type = "boolean", .description = "Enable peers to tunnel through this instance as a room.", .default_value = { .kind = k_kind_bool, .bool_value = true } }, + { .name = "room_name", .type = "string", .description = "Name of the room.", .default_value = { .kind = k_kind_string, .string_value = "tilde friends tunnel" } }, + { .name = "seeds_host", + .type = "string", + .description = "Hostname for seed connections.", + .default_value = { .kind = k_kind_string, .string_value = "seeds.tildefriends.net" } }, + { .name = "account_registration", .type = "boolean", .description = "Allow registration of new accounts.", .default_value = { .kind = k_kind_bool, .bool_value = true } }, + { .name = "replication_hops", + .type = "integer", + .description = "Number of hops to replicate (1 = direct follows, 2 = follows of follows, etc.).", + .default_value = { .kind = k_kind_int, .int_value = 2 } }, + { .name = "delete_stale_feeds", + .type = "boolean", + .description = "Periodically delete feeds that aren't visible from local accounts or related follows.", + .default_value = { .kind = k_kind_bool, .bool_value = false } }, + { .name = "talk_to_strangers", + .type = "boolean", + .description = "Whether connections are accepted from accounts that aren't in the replication range or otherwise already known.", + .default_value = { .kind = k_kind_bool, .bool_value = true } }, +}; + +static const setting_t* _util_get_setting(const char* name, value_kind_t kind) +{ + for (int i = 0; i < tf_countof(k_settings); i++) + { + if (strcmp(k_settings[i].name, name) == 0 && k_settings[i].default_value.kind == kind) + { + return &k_settings[i]; + } + } + tf_printf("Did not find global setting of type %s: %s.\n", k_kind_name[kind], name); + return NULL; +} + +bool tf_util_get_default_global_setting_bool(const char* name) +{ + const setting_t* setting = _util_get_setting(name, k_kind_bool); + return setting ? setting->default_value.bool_value : false; +} + +int tf_util_get_default_global_setting_int(const char* name) +{ + const setting_t* setting = _util_get_setting(name, k_kind_int); + return setting ? setting->default_value.int_value : 0; +} + +const char* tf_util_get_default_global_setting_string(const char* name) +{ + const setting_t* setting = _util_get_setting(name, k_kind_string); + return setting && setting->default_value.string_value ? setting->default_value.string_value : ""; } static JSValue _util_defaultGlobalSettings(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) { - typedef struct _setting_t - { - const char* name; - const char* type; - const char* description; - JSValue default_value; - } setting_t; - - const setting_t k_settings[] = { - { .name = "code_of_conduct", .type = "textarea", .description = "Code of conduct presented at sign-in." }, - { .name = "blob_fetch_age_seconds", - .type = "integer", - .description = "Only blobs mentioned more recently than this age will be automatically fetched.", - .default_value = _is_mobile() ? JS_NewInt32(context, (int)(0.5f * 365 * 24 * 60 * 60)) : JS_UNDEFINED }, - { .name = "blob_expire_age_seconds", - .type = "integer", - .description = "Blobs older than this will be automatically deleted.", - .default_value = _is_mobile() ? JS_NewInt32(context, (int)(1.0f * 365 * 24 * 60 * 60)) : JS_UNDEFINED }, - { .name = "fetch_hosts", .type = "string", .description = "Comma-separated list of host names to which HTTP fetch requests are allowed. None if empty." }, - { .name = "http_redirect", .type = "string", .description = "If connecting by HTTP and HTTPS is configured, Location header prefix (ie, \"http://example.com\")" }, - { .name = "index", .type = "string", .description = "Default path.", .default_value = JS_NewString(context, "/~core/ssb/") }, - { .name = "index_map", .type = "textarea", .description = "Mappings from hostname to redirect path, one per line, as in: \"www.tildefriends.net=/~core/index/\"" }, - { .name = "peer_exchange", - .type = "boolean", - .description = "Enable discovery of, sharing of, and connecting to internet peer strangers, including announcing this instance.", - .default_value = JS_FALSE }, - { .name = "replicator", .type = "boolean", .description = "Enable message and blob replication.", .default_value = JS_TRUE }, - { .name = "room", .type = "boolean", .description = "Enable peers to tunnel through this instance as a room.", .default_value = JS_TRUE }, - { .name = "room_name", .type = "string", .description = "Name of the room.", .default_value = JS_NewString(context, "tilde friends tunnel") }, - { .name = "seeds_host", .type = "string", .description = "Hostname for seed connections.", .default_value = JS_NewString(context, "seeds.tildefriends.net") }, - { .name = "account_registration", .type = "boolean", .description = "Allow registration of new accounts.", .default_value = JS_TRUE }, - { .name = "replication_hops", - .type = "integer", - .description = "Number of hops to replicate (1 = direct follows, 2 = follows of follows, etc.).", - .default_value = JS_NewInt32(context, 2) }, - { .name = "delete_stale_feeds", - .type = "boolean", - .description = "Periodically delete feeds that aren't visible from local accounts or related follows.", - .default_value = JS_FALSE }, - { .name = "talk_to_strangers", - .type = "boolean", - .description = "Whether connections are accepted from accounts that aren't in the replication range or otherwise already known.", - .default_value = JS_TRUE }, - }; - JSValue settings = JS_NewObject(context); for (int i = 0; i < tf_countof(k_settings); i++) { JSValue entry = JS_NewObject(context); JS_SetPropertyStr(context, entry, "type", JS_NewString(context, k_settings[i].type)); JS_SetPropertyStr(context, entry, "description", JS_NewString(context, k_settings[i].description)); - JS_SetPropertyStr(context, entry, "default_value", k_settings[i].default_value); + switch (k_settings[i].default_value.kind) + { + case k_kind_bool: + JS_SetPropertyStr(context, entry, "default_value", JS_NewBool(context, k_settings[i].default_value.bool_value)); + break; + case k_kind_int: + JS_SetPropertyStr(context, entry, "default_value", JS_NewInt32(context, k_settings[i].default_value.int_value)); + break; + case k_kind_string: + JS_SetPropertyStr( + context, entry, "default_value", k_settings[i].default_value.string_value ? JS_NewString(context, k_settings[i].default_value.string_value) : JS_UNDEFINED); + break; + } JS_SetPropertyStr(context, settings, k_settings[i].name, entry); } return settings; diff --git a/src/util.js.h b/src/util.js.h index 8a7541b4..2c434d1f 100644 --- a/src/util.js.h +++ b/src/util.js.h @@ -173,4 +173,25 @@ const char* tf_util_function_to_string(void* function); */ #define tf_countof(a) ((int)(sizeof((a)) / sizeof(*(a)))) +/** +** Get the default value of a global setting as a boolean. +** @param name The setting name. +** @return The default value. +*/ +bool tf_util_get_default_global_setting_bool(const char* name); + +/** +** Get the default value of a global setting as an integer. +** @param name The setting name. +** @return The default value. +*/ +int tf_util_get_default_global_setting_int(const char* name); + +/** +** Get teh default value of a global setting as a string. +** @param name The setting name. +** @return The default value. +*/ +const char* tf_util_get_default_global_setting_string(const char* name); + /** @} */