/** * @brief If message contains subscribe:true, add the message to subscription list using the default key '/category/method'. * * This is equivalent to LSSubscriptionAdd(sh, key, message, lserror) * where the key is LSMessageGetKind(message). * * @param sh * @param message * @param subscribed * @param lserror * * @retval */ bool LSSubscriptionProcess (LSHandle *sh, LSMessage *message, bool *subscribed, LSError *lserror) { JSchemaInfo schemaInfo; jschema_info_init(&schemaInfo, jschema_all(), NULL, NULL); bool retVal = false; bool subscribePayload = false; jvalue_ref subObj = NULL; const char *payload = LSMessageGetPayload(message); jvalue_ref object = jdom_parse(j_cstr_to_buffer(payload), DOMOPT_NOOPT, &schemaInfo); if (jis_null(object)) { _LSErrorSet(lserror, MSGID_LS_INVALID_JSON, -1, "Unable to parse JSON: %s", payload); goto exit; } if (!jobject_get_exists(object, J_CSTR_TO_BUF("subscribe"), &subObj) || subObj == NULL || !jis_boolean(subObj)) { subscribePayload = false; /* FIXME: I think retVal should be false, but I don't know if anyone * is relying on this behavior. If set to false, make sure to set * LSError */ retVal = true; } else { (void)jboolean_get(subObj, &subscribePayload);/* TODO: handle appropriately */ retVal = true; } if (subscribePayload) { const char *key = LSMessageGetKind(message); retVal = LSSubscriptionAdd(sh, key, message, lserror); } if (retVal && subscribePayload) { *subscribed = true; } else { *subscribed = false; } exit: j_release(&object); return retVal; }
const char *jvalue_tostring_simple(jvalue_ref val) { JSchemaInfo schemainfo; JSchemaResolverRef resolver = NULL; JErrorCallbacksRef errors = NULL; jschema_info_init(&schemainfo, jschema_all(), resolver, errors); return jvalue_tostring_internal_layer1(val, &schemainfo, false); }
bool _CatalogHandleCancel(_Catalog *catalog, LSMessage *cancelMsg, LSError *lserror) { JSchemaInfo schemaInfo; jschema_info_init(&schemaInfo, jschema_all(), NULL, NULL); const char *sender; int token; jvalue_ref tokenObj = NULL; const char *payload = LSMessageGetPayload(cancelMsg); jvalue_ref object = jdom_parse(j_cstr_to_buffer(payload), DOMOPT_NOOPT, &schemaInfo); if (jis_null(object)) { _LSErrorSet(lserror, MSGID_LS_INVALID_JSON, -EINVAL, "Invalid json"); goto error; } sender = LSMessageGetSender(cancelMsg); if (!jobject_get_exists(object, J_CSTR_TO_BUF("token"), &tokenObj) || tokenObj == NULL || !jis_number(tokenObj)) { _LSErrorSet(lserror, MSGID_LS_INVALID_JSON, -EINVAL, "Invalid json"); goto error; } (void)jnumber_get_i32(tokenObj, &token);/* TODO: handle appropriately */ char *uniqueToken = g_strdup_printf("%s.%d", sender, token); _CatalogCallCancelNotifications(catalog, uniqueToken); _CatalogRemoveToken(catalog, uniqueToken, true); g_free(uniqueToken); j_release(&object); return true; error: j_release(&object); return false; }
static int my_bounce_null(void *ctxt) { bounce_breakpoint("null"); PJ_LOG_TRACE("null"); JSAXContextRef spring = (JSAXContextRef)ctxt; #if !BYPASS_SCHEMA #if SHORTCUT_SCHEMA_ALL if (spring->m_validation->m_state->m_schema != jschema_all()) #endif { if (!jschema_null(spring, spring->m_validation)) { if (SCHEMA_HANDLER_FAILED(spring)) return 0; } } #endif DEREF_CALLBACK(spring->m_handlers->yajl_null, ctxt); }
static int my_bounce_boolean(void *ctxt, int boolVal) { bounce_breakpoint(); PJ_LOG_TRACE("%s", (boolVal ? "true" : "false")); JSAXContextRef spring = (JSAXContextRef)ctxt; #if !BYPASS_SCHEMA #if SHORTCUT_SCHEMA_ALL if (spring->m_validation->m_state->m_schema != jschema_all()) #endif { if (!jschema_bool(spring, spring->m_validation, boolVal)) { if (SCHEMA_HANDLER_FAILED(spring)) return 0; } } #endif DEREF_CALLBACK(spring->m_handlers->yajl_boolean, ctxt, boolVal); }
static int my_bounce_number(void *ctxt, const char *numberVal, unsigned int numberLen) { bounce_breakpoint(numberVal); PJ_LOG_TRACE("%.*s", numberLen, numberVal); JSAXContextRef spring = (JSAXContextRef)ctxt; #if !BYPASS_SCHEMA #if SHORTCUT_SCHEMA_ALL if (spring->m_validation->m_state->m_schema != jschema_all()) #endif { if (!jschema_num(spring, spring->m_validation, j_str_to_buffer((char *)numberVal, numberLen))) { if (SCHEMA_HANDLER_FAILED(spring)) return 0; } } #endif DEREF_CALLBACK(spring->m_handlers->yajl_number, ctxt, numberVal, numberLen); }
static int my_bounce_map_key(void *ctxt, const unsigned char *str, unsigned int strLen) { bounce_breakpoint(); PJ_LOG_TRACE("%.*s", strLen, str); JSAXContextRef spring = (JSAXContextRef)ctxt; #if !BYPASS_SCHEMA #if SHORTCUT_SCHEMA_ALL if (spring->m_validation->m_state->m_schema != jschema_all()) #endif { if (!jschema_key(spring, spring->m_validation, j_str_to_buffer((char *)str, strLen))) { if (SCHEMA_HANDLER_FAILED(spring)) return 0; } } #endif DEREF_CALLBACK(spring->m_handlers->yajl_map_key, ctxt, str, strLen); }
/** ******************************************************************************* * @brief Get the service name from a "ServceStatus" message. The name is * allocated and should be freed. * * @param message IN message * * @retval name string on success * @retval NULL on error ******************************************************************************* */ char* LSTransportServiceStatusSignalGetServiceName(_LSTransportMessage *message) { JSchemaInfo schemaInfo; jschema_info_init(&schemaInfo, jschema_all(), NULL, NULL); LS_ASSERT(_LSTransportMessageGetType(message) == _LSTransportMessageTypeServiceDownSignal || _LSTransportMessageGetType(message) == _LSTransportMessageTypeServiceUpSignal); char *service_name = NULL; jvalue_ref service_name_obj = NULL; const char *payload = _LSTransportMessageGetPayload(message); if (!payload) { LOG_LS_ERROR(MSGID_LS_INVALID_JSON, 0, "Unable to get payload from message"); return NULL; } /* get the serviceName part of the JSON object */ jvalue_ref payload_json = jdom_parse(j_cstr_to_buffer(payload), DOMOPT_NOOPT, &schemaInfo); bool ret = jobject_get_exists(payload_json, J_CSTR_TO_BUF(SERVICE_STATUS_SERVICE_NAME), &service_name_obj); if (ret) { raw_buffer service_name_buf = jstring_get_fast(service_name_obj); service_name = g_strndup(service_name_buf.m_str, service_name_buf.m_len); } else { LOG_LS_ERROR(MSGID_LS_INVALID_JSON, 0, "Unable to get service name string from payload: %s", payload); } j_release(&payload_json); return service_name; }
static bool jsax_parse_internal(PJSAXCallbacks *parser, raw_buffer input, JSchemaInfoRef schemaInfo, void **ctxt, bool logError, bool comments) { yajl_status parseResult; PJ_LOG_TRACE("Parsing '%.*s'", RB_PRINTF(input)); if (parser == NULL) parser = &no_callbacks; if (jis_null_schema(schemaInfo->m_schema)) { PJ_LOG_WARN("Cannot match against schema that matches nothing: Schema pointer = %p", schemaInfo->m_schema); return false; } if (schemaInfo->m_schema == jschema_all()) { PJ_LOG_DBG("Using default empty schema for matching"); } else { if (schemaInfo->m_resolver == NULL) { PJ_LOG_DBG("No resolver specified for the schema. Make sure %p doesn't contain any external references", schemaInfo->m_schema); } } if (schemaInfo->m_errHandler == NULL) schemaInfo->m_errHandler = &null_err_handler; #ifdef _DEBUG logError = true; #endif yajl_callbacks yajl_cb = { (pj_yajl_null)parser->m_null, // yajl_null (pj_yajl_boolean)parser->m_boolean, // yajl_boolean NULL, // yajl_integer NULL, // yajl_double (pj_yajl_number)parser->m_number, // yajl_number (pj_yajl_string)parser->m_string, // yajl_stirng (pj_yajl_start_map)parser->m_objStart, // yajl_start_map (pj_yajl_map_key)parser->m_objKey, // yajl_map_key (pj_yajl_end_map)parser->m_objEnd, // yajl_end_map (pj_yajl_start_array)parser->m_arrStart, // yajl_start_array (pj_yajl_end_array)parser->m_arrEnd, // yajl_end_array }; yajl_parser_config yajl_opts = { comments, // comments are not allowed 0, // currently only UTF-8 will be supported for input. }; PJSAXContext internalCtxt = { .ctxt = (ctxt != NULL ? *ctxt : NULL), .m_handlers = &yajl_cb, .m_errors = schemaInfo->m_errHandler, }; #if !BYPASS_SCHEMA internalCtxt.m_validation = jschema_init(schemaInfo); if (internalCtxt.m_validation == NULL) { PJ_LOG_WARN("Failed to initialize validation state machine"); return false; } #endif yajl_handle handle = yajl_alloc(&my_bounce, &yajl_opts, NULL, &internalCtxt); parseResult = yajl_parse(handle, (unsigned char *)input.m_str, input.m_len); if (ctxt != NULL) *ctxt = jsax_getContext(&internalCtxt); switch (parseResult) { case yajl_status_ok: break; case yajl_status_client_canceled: if (ERR_HANDLER_FAILED(schemaInfo->m_errHandler, m_unknown, &internalCtxt)) goto parse_failure; PJ_LOG_WARN("Client claims they handled an unknown error in '%.*s'", (int)input.m_len, input.m_str); break; case yajl_status_insufficient_data: if (ERR_HANDLER_FAILED(schemaInfo->m_errHandler, m_parser, &internalCtxt)) goto parse_failure; PJ_LOG_WARN("Client claims they handled incomplete JSON input provided '%.*s'", (int)input.m_len, input.m_str); break; case yajl_status_error: default: if (ERR_HANDLER_FAILED(schemaInfo->m_errHandler, m_unknown, &internalCtxt)) goto parse_failure; PJ_LOG_WARN("Client claims they handled an unknown error in '%.*s'", (int)input.m_len, input.m_str); break; } #if !BYPASS_SCHEMA jschema_state_release(&internalCtxt.m_validation); #endif #ifndef NDEBUG assert(yajl_get_error(handle, 0, NULL, 0) == NULL); #endif yajl_free(handle); return true; parse_failure: if (UNLIKELY(logError)) { unsigned char *errMsg = yajl_get_error(handle, 1, (unsigned char *)input.m_str, input.m_len); PJ_LOG_WARN("Parser reason for failure:\n'%s'", errMsg); yajl_free_error(handle, errMsg); } #if !BYPASS_SCHEMA jschema_state_release(&internalCtxt.m_validation); #endif yajl_free(handle); return false; } bool jsax_parse_ex(PJSAXCallbacks *parser, raw_buffer input, JSchemaInfoRef schemaInfo, void **ctxt, bool logError) { return jsax_parse_internal(parser, input, schemaInfo, ctxt, logError, false); } bool jsax_parse(PJSAXCallbacks *parser, raw_buffer input, JSchemaInfoRef schema) { assert(schema != NULL); return jsax_parse_ex(parser, input, schema, NULL, false); }
void TestSchema::testSimpleSchema() { JSchemaInfo schemaInfo; jschema_info_init(&schemaInfo, jschema_all(), NULL, NULL); QVERIFY(jsax_parse(NULL, J_CSTR_TO_BUF("{}"), &schemaInfo)); }