int main(int argc, char *argv[]) { cJSON *json = NULL; const char *commands[] = { "uci show info.@info[0].hardware | awk -F '=' '{print $2}'", "uci show info.@info[0].version | awk -F '=' '{print $2}'", "cat /proc/uptime | awk '{print $1}'", NULL }; const char *entrys[] = { "hardware", "version", "uptime", NULL }; commandGetter(&json, commands, entrys); printf("Content-Type:application/json\n\n"); char *out = cJSON_Print(json); cJSON_Minify(out); printf("%s\n", out); fflush(stdout); cJSON_Delete(json); free(out); return EXIT_SUCCESS; }
TEST(PstatTests, JSONMarshalliingTests) { char *jsonStr1 = ReadFile(UNIT_TEST_JSON_FILE_NAME); if (NULL != jsonStr1) { cJSON_Minify(jsonStr1); /* Workaround : cJSON_Minify does not remove all the unwanted characters from the end. Here is an attempt to remove those characters */ int len = strlen(jsonStr1); while (len > 0) { if (jsonStr1[--len] == '}') { break; } } jsonStr1[len + 1] = 0; OicSecPstat_t* pstat = JSONToPstatBin(jsonStr1); EXPECT_TRUE(NULL != pstat); char* jsonStr2 = BinToPstatJSON(pstat); printf("BinToPstatJSON Dump:\n%s\n\n", jsonStr2); EXPECT_STRNE(jsonStr1, jsonStr2); OICFree(jsonStr1); OICFree(jsonStr2); OICFree(pstat); } else { printf("Please copy %s into unittest folder\n", UNIT_TEST_JSON_FILE_NAME); } }
/* Returns 1 if app info is found within the "app_id" * application directory. * Returns 0 otherwise. * * If successful, info is parsed from info/desc.json. */ int get_info(cJSON **info, const char *dir, const char *app_id, ngx_pool_t *pool) { char *data = NULL; cJSON *json = NULL; FILE *fp = NULL; size_t len, read; int ret = 1; struct stat st; /* Read description JSON file */ const char *fname = "info/info.json"; char file [strlen(dir) + strlen(app_id) + strlen(fname) + 3]; sprintf(file, "%s/%s/%s", dir, app_id, fname); fp = fopen(file, "r"); if(fp == NULL) { fprintf(stderr, "Cannot open %s.\n", file); ret = 0; goto out; } stat(file, &st); len = st.st_size; data = (char *)malloc(len+1); if(data == NULL) { fprintf(stderr, "Can not allocate memory: %s", strerror(errno)); ret = 0; goto out; } read = fread(data, len, 1, fp); if(read != 1) { fprintf(stderr, "Cannot read from %s.\n", file); ret = 0; goto out; } /* Get rid of comments */ cJSON_Minify(data); /* Parse relevant JSON content */ json = cJSON_Parse(data, pool); if(json == NULL) { fprintf(stderr, "Error parsing JSON before [%s].\n", cJSON_GetErrorPtr()); ret = 0; goto out; } *info = json; out: /* Do not delete json: * If it is added to some json tree, it will be deleted as a branch. * If not, the caller is responsible to delete it. */ if (data) free(data); if (fp) fclose(fp); return ret; }
/*----------------------------------------------------------------------------*/ ngx_int_t rp_bazaar_cmd_handler(ngx_http_request_t *r) { ngx_http_rp_loc_conf_t *lc; rp_bazaar_ctx_t *ctx; size_t i = 0; ctx = ngx_pcalloc(r->pool, sizeof(rp_bazaar_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ctx->redirect = ngx_pcalloc(r->pool, c_redirect_len); if (ctx->redirect == NULL) { return NGX_ERROR; } ctx->json_root = NULL; ctx->finalize_on_post_handler = 0; ctx->in_buffer = NULL; ctx->in_buffer_len = 0; ctx->in_status = 0; ngx_http_set_ctx(r, ctx, ngx_http_rp_module); lc = ngx_http_get_module_loc_conf(r, ngx_http_rp_module); /* Just test local directory here - we would need to check it for almost * all calls anyway */ if(lc->bazaar_dir.data == NULL) { fprintf(stderr, "Bazaar local directory not found\n"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->json_root = cJSON_CreateObject(r->pool); if(ctx->json_root == NULL) { fprintf(stderr, "Cannot allocate cJSON object\n"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* Bazaar commands */ for(i = 0; bazaar_cmds[i].name != NULL; i++) { ngx_str_t arg_name = { strlen(bazaar_cmds[i].name), (u_char *)bazaar_cmds[i].name }; ngx_uint_t arg_key = ngx_hash_key(arg_name.data, arg_name.len); ngx_http_variable_value_t *arg_val = NULL; int rc; char **arg_argv = NULL; int arg_argc = 0; arg_val = ngx_http_get_variable(r, &arg_name, arg_key); /* check validity of the specified http variables * note: not all attributes of arg_value are set within ngx_http_get_variable, thus * the order of the following checks are important otherwise it could come to the usage * of uninitialized value what would lead to invalid processing */ if (!arg_val) continue; if (arg_val->not_found == 1) continue; if (arg_val->valid == 0) continue; arg_val->data[arg_val->len] = '\0'; arg_argc = rp_module_cmd_parse_args((const char *)arg_val->data, arg_val->len, &arg_argv); fprintf(stderr, "Calling application: %s\n", &bazaar_cmds[i].name[4]); /* Install/Remove special case */ if ( !strncmp(&bazaar_cmds[i].name[4], "install", 7) || !strncmp(&bazaar_cmds[i].name[4], "remove", 6) ) { if(arg_argv) { for(i = 0; i < (size_t)arg_argc; i++) { if(arg_argv[i]) { free(arg_argv[i]); arg_argv[i] = NULL; } } free(arg_argv); } return rp_bazaar_install(r); } if((rc = bazaar_cmds[i].func(r, &ctx->json_root, arg_argc, arg_argv)) < 0) { /* error - fill the output buffer and send it back */ fprintf(stderr, "Application %s failed: %d\n", bazaar_cmds[i].name, rc); } if(arg_argv) { for(i = 0; i < (size_t)arg_argc; i++) { if(arg_argv[i]) { free(arg_argv[i]); arg_argv[i] = NULL; } } free(arg_argv); } /* Prepare response header & body */ return rp_module_send_response(r, &ctx->json_root); } int ret = 0; /* Unknown command response */ if (i >= sizeof(bazaar_cmds)/sizeof(rp_module_cmd_t)) { rp_module_cmd_error(&ctx->json_root, "Unknown command.", NULL, r->pool); return rp_module_send_response(r, &ctx->json_root); } /* Default Bazaar entry point - list of applications with versions */ cJSON *json_tok = NULL; char *host = (char *)r->headers_in.server.data; char mac[18]; sprintf(mac, "00:00:00:00:00:00"); if (rp_bazaar_get_mac("/sys/class/net/eth0/address", mac)) { fprintf(stderr, "Cannot obtain MAC address.\n"); } static unsigned long long dna = 0; if (!dna || dna == 1) { if (rp_bazaar_get_dna(&dna)) { fprintf(stderr, "Cannot obtain DNA number.\n"); } } char dna_s[64]; sprintf(dna_s, "%016llx", dna); /* Get Ecosystem version */ char ecoversion[64]; sprintf(ecoversion, "unknown"); cJSON *ecoinfo = NULL; if (!get_info(&ecoinfo, (const char *)lc->bazaar_dir.data, "", r->pool)) { fprintf(stderr, "Cannot obtain Ecosystem version.\n"); } else { if (ecoinfo != NULL) { cJSON *j_ver = cJSON_GetObjectItem(ecoinfo, "version"); if(j_ver == NULL) { fprintf(stderr, "Cannot get version from ecoinfo JSON.\n"); } else { strncpy(ecoversion, j_ver->valuestring, sizeof ecoversion); cJSON_Delete(j_ver, r->pool); } cJSON_Delete(ecoinfo, r->pool); } } /* Populate JSON */ cJSON_AddItemToObject(ctx->json_root, "version", cJSON_CreateString(ecoversion, r->pool), r->pool); cJSON_AddItemToObject(ctx->json_root, "dna", cJSON_CreateString(dna_s, r->pool), r->pool); cJSON_AddItemToObject(ctx->json_root, "mac", cJSON_CreateString(mac, r->pool), r->pool); // TODO: Serial number? cJSON_AddItemToObject(ctx->json_root, "host", cJSON_CreateString(host, r->pool), r->pool); cJSON *apps_root; cJSON_AddItemToObject(ctx->json_root, "apps", apps_root=cJSON_CreateObject(r->pool), r->pool); if(apps_root == NULL) { fprintf(stderr, "Can not allocate cJSON object\n"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } fprintf(stderr, "Making list of apps\n"); /* Add the non-verbose list of apps */ rp_bazaar_app_get_local_list((const char *)lc->bazaar_dir.data, &apps_root, r->pool, 0); /* Issue a POST with JSON defined above to Bazaar server */ char *js = cJSON_Print(ctx->json_root, r->pool); cJSON_Minify(js); fprintf(stderr, "Bazaar handshake:\n%s", js); char *jse = NULL; char *jsp = NULL; char *bazaar_dv = NULL; const char *c_payload = "payload="; const char *c_device = "/device"; jse = url_encode(js); jsp = malloc(strlen(jse) + strlen(c_payload) + 1); if (!jsp) { fprintf(stderr, "Cannot malloc() payload.\n"); ret = NGX_HTTP_INTERNAL_SERVER_ERROR; goto out; } sprintf(jsp, "%s%s", c_payload, jse); bazaar_dv = (char *)malloc(strlen((char *)lc->bazaar_server.data) + strlen(c_device) + 1); if (!bazaar_dv) { fprintf(stderr, "Cannot malloc() device.\n"); ret = NGX_HTTP_INTERNAL_SERVER_ERROR; goto out; } sprintf(bazaar_dv, "%s%s", lc->bazaar_server.data, c_device); fprintf(stderr, "post bazaar_dv %s\n", bazaar_dv); post_resp_t resp = { NULL, 0 }; if (post(jsp, bazaar_dv, &resp)) { if (resp.data) free(resp.data); /* Redirect to Bazaar access error */ fprintf(stderr, "Cannot access %s.\n", bazaar_dv); snprintf(ctx->redirect, c_redirect_len, "http://%s/error_bazaar_access.html", host); goto out; } /* Get token from POST response */ if (resp.data) { fprintf(stderr,"Bazaar handshake response:\n%s", resp.data); json_tok = cJSON_Parse(resp.data, r->pool); if (!json_tok) { /* Redirect to Bazaar protocol error */ fprintf(stderr,"No JSON found in the following response:\n\"%s\"\n", resp.data); snprintf(ctx->redirect, c_redirect_len, "http://%s/error_bazaar_proto.html", host); } else { cJSON *jtok = cJSON_GetObjectItem(json_tok, "token"); if (!jtok) { /* Redirect to Bazaar protocol error */ fprintf(stderr, "No token found in the following JSON:\n\"%s\"\n", resp.data); snprintf(ctx->redirect, c_redirect_len, "http://%s/error_bazaar_proto.html", host); } else { /* Redirect to Bazaar with token */ snprintf(ctx->redirect, c_redirect_len, "%s/token/%s", lc->bazaar_server.data, jtok->valuestring); /* Store token for session control */ strncpy(g_token, jtok->valuestring, c_token_len); g_token[c_token_len - 1] = '\0'; } } free(resp.data); } out: if (jsp) free(jsp); if (jse) free(jse); if (bazaar_dv) free(bazaar_dv); //TODO: Is ctx->json_root handled by the pool deallocator? //if (ctx->json_root) cJSON_Delete(ctx->json_root, r->pool); if (json_tok) cJSON_Delete(json_tok, r->pool); if (ret) return ret; fprintf(stderr, "Redirecting to: %s\n", ctx->redirect); return rp_module_redirect(r, ctx->redirect); }
/** * @brief Handler function for operation. * * Function parses the POST request, which is defined by JSON packet and * installs/removes the archive. * * @param[in] r HTTP request as defined by NGINX framework * @param[out] act Bazaar action * @retval 0 successful operation * @retval !=0 failure */ int rp_bazaar_interpret(ngx_http_request_t *r, action_e *act) { rp_bazaar_ctx_t *ctx; cJSON *req_body = NULL; cJSON *j_cmd = NULL; cJSON *j_url = NULL; cJSON *j_app = NULL; cJSON *j_md5 = NULL; cJSON *j_tok = NULL; char *urld = NULL; char *action = NULL; int ret = 0; fprintf(stderr, "%s\n", __FUNCTION__); *act = eUnknown; ctx = ngx_http_get_module_ctx(r, ngx_http_rp_module); if(ctx == NULL) { fprintf(stderr, "%s: Cannot get request context\n", __FUNCTION__); return -1; } /* check if this is a POST operation */ if(!(r->method & NGX_HTTP_POST)) { return rp_module_cmd_error(&ctx->json_root, "Expected POST method", NULL, r->pool); } /* check for payload buffers */ if((ctx->in_buffer_len == 0) || (ctx->in_buffer == NULL) || (ctx->in_status != 0)) { fprintf(stderr, "Body is empty, unknown error\n"); return -1; } /* parse incoming body to cJSON and search for 'params' */ fprintf(stderr, "Bazaar install/remove: Received body: %s\n", ctx->in_buffer); urld = url_decode(ctx->in_buffer); cJSON_Minify(urld); /* Get rid of "payload=" header */ char *urld_strip = memchr(urld, '{', 10); req_body = cJSON_Parse(urld_strip, r->pool); if (urld) free (urld); if(req_body == NULL) { fprintf(stderr, "Can not parse incoming body to JSON\n"); return -1; } /* "command" object */ j_cmd = cJSON_GetObjectItem(req_body, "command"); if(j_cmd == NULL) { cJSON_Delete(req_body, r->pool); fprintf(stderr, "Can not find 'command' in req body\n"); return -1; } /* Install/Upgrade */ if ( !strncmp(j_cmd->valuestring, "install", sizeof("install")) ) { *act = eInstall; action = j_cmd->valuestring; } if ( !strncmp(j_cmd->valuestring, "upgrade", sizeof("upgrade")) ) { *act = eUpgrade; action = j_cmd->valuestring; } if ( (*act == eInstall) || (*act == eUpgrade) ) { /* "archive" object */ j_url = cJSON_GetObjectItem(req_body, "archive"); if(j_url == NULL) { cJSON_Delete(req_body, r->pool); fprintf(stderr, "Can not find 'archive' in req body\n"); return -1; } /* "md5" object */ j_md5 = cJSON_GetObjectItem(req_body, "md5"); if(j_md5 == NULL) { cJSON_Delete(req_body, r->pool); fprintf(stderr, "Can not find 'md5' in req body\n"); return -1; } } /* Uninstall */ if (!strncmp(j_cmd->valuestring, "uninstall", sizeof("uninstall"))) { *act = eRemove; action = "remove"; } /* Unknown action */ if (!action) { cJSON_Delete(req_body, r->pool); fprintf(stderr, "Unknown action: %s\n", j_cmd->valuestring); return -1; } /* "app_id" object */ j_app = cJSON_GetObjectItem(req_body, "app_id"); if(j_app == NULL) { cJSON_Delete(req_body, r->pool); fprintf(stderr, "Can not find 'app_id' in req body\n"); return -1; } /* "token" object */ j_tok = cJSON_GetObjectItem(req_body, "token"); if(j_tok == NULL) { cJSON_Delete(req_body, r->pool); fprintf(stderr, "Can not find 'token' in req body\n"); return -1; } if (strncmp(j_tok->valuestring, g_token, c_token_len)) { cJSON_Delete(req_body, r->pool); fprintf(stderr, "Unauthorized Bazaar %s request\n", action); return -1; } /* Call bazaar script */ char cmd[256]; switch (*act) { case eInstall: case eUpgrade: fprintf(stderr, "Installing: %s\n", j_url->valuestring); sprintf(cmd, "bazaar install %s %s %s", j_app->valuestring, j_url->valuestring, j_md5->valuestring); break; case eRemove: fprintf(stderr, "Removing: %s\n", j_app->valuestring); sprintf(cmd, "bazaar remove %s", j_app->valuestring); break; default: fprintf(stderr, "Unknown Bazaar action: %s\n", j_cmd->valuestring); ret = -1; goto out; } ret = system(cmd); out: /* release our resources */ cJSON_Delete(req_body, r->pool); return ret; }