summaryrefslogtreecommitdiffstats
path: root/afb-client/bower_components/foundation-icon-fonts/svgs/fi-guide-dog.svg
blob: c20f008ed870fad868a485f755e1d28b9fb0d09f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
<g>
	<path d="M39.818,24.963L51.575,36.72c0.033,0.035,0.067,0.069,0.102,0.102l0.095,0.095l0.009-0.009
		c0.35,0.285,0.791,0.464,1.279,0.464c1.123,0,2.034-0.911,2.034-2.035c0-0.733-0.391-1.37-0.973-1.728l-11.7-11.699
		c-0.373-0.425-0.913-0.698-1.523-0.698c-1.123,0-2.034,0.911-2.034,2.034C38.864,23.971,39.246,24.604,39.818,24.963z"/>
	<path d="M53.059,65.729V40.69h-26.9c-0.147,0-0.29,0.037-0.432,0.091L14.76,34.45l-0.009,0.015
		c-0.354-0.183-0.749-0.296-1.175-0.296c-1.421,0-2.573,1.152-2.573,2.572c0,0.909,0.474,1.704,1.185,2.162l-0.019,0.033
		l11.112,6.416c-0.429,1.868-0.685,4.162-0.685,6.651c0,5.261,1.133,9.669,2.664,10.936L18.996,73.79
		c-0.464,0.595-0.751,1.333-0.751,2.146c0,1.939,1.572,3.512,3.512,3.512c1.134,0,2.132-0.547,2.774-1.382l0.06,0.035l7.327-12.691
		L39.245,78.1l0.06-0.034c0.642,0.835,1.64,1.382,2.774,1.382c1.94,0,3.512-1.572,3.512-3.512c0-0.812-0.287-1.551-0.751-2.146
		l-4.732-8.195c2.467,0.142,5.146,0.22,7.951,0.22C49.78,65.815,51.452,65.785,53.059,65.729z"/>
	<path d="M70.685,63.13c1.151-0.649,2.112-3.049,2.597-6.305L57.059,40.602v22.686L50.995,73.79
		c-0.464,0.595-0.751,1.333-0.751,2.146c0,1.939,1.572,3.512,3.512,3.512c1.134,0,2.132-0.547,2.774-1.382l0.06,0.035l7.327-12.691
		L71.245,78.1l0.06-0.034c0.642,0.835,1.64,1.382,2.774,1.382c1.94,0,3.512-1.572,3.512-3.512c0-0.812-0.287-1.551-0.751-2.146
		L70.685,63.13z"/>
	<path d="M88.997,41.676c0-0.83-0.409-1.56-1.031-2.015l-3.906-3.906V31.69c0-1.528-0.879-2.837-2.151-3.49l-5.054-2.918
		l-0.014,0.024c-0.425-0.252-0.898-0.426-1.406-0.503l-2.454-4.25l-5.098,8.83l-8.193,8.192l13.919,13.919
		c-0.016-1.062-0.069-2.091-0.17-3.058l2.746-2.746h7.875h2v-0.027l2.174-2.174l-0.01-0.01
		C88.698,43.023,88.997,42.386,88.997,41.676z"/>
</g>
</svg>
'#n419'>419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469
/*
 * Copyright (C) 2016 "IoT.bzh"
 * Author Fulup Ar Foll <fulup@iot.bzh>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, something express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Reference:
 *   Json load using json_unpack https://jansson.readthedocs.io/en/2.9/apiref.html#parsing-and-validating-values
 */

#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>

#include "ctl-config.h"

int ActionLabelToIndex(CtlActionT*actions, const char* actionLabel) {
    if (actions) {
        for (int idx = 0; actions[idx].uid; idx++) {
            if (!strcasecmp(actionLabel, actions[idx].uid)) return idx;
        }
    }

    return -1;
}

void ActionExecUID(afb_req_t request, CtlConfigT *ctlConfig, const char *uid, json_object *queryJ) {
    for (int i = 0; ctlConfig->sections[i].key != NULL; i++) {
        if (ctlConfig->sections[i].actions) {
            for (int j = 0; ctlConfig->sections[i].actions[j].uid != NULL; j++) {
                if (strcmp(ctlConfig->sections[i].actions[j].uid, uid) == 0) {
                    CtlSourceT source;
                    source.uid = ctlConfig->sections[i].actions[j].uid;
                    source.api = ctlConfig->sections[i].actions[j].api;
                    source.request = request;

                    ActionExecOne(&source, &ctlConfig->sections[i].actions[j], queryJ);
                }
            }
        }
    }
}

void HandleApiCallActionResponseFromVerbCall(void *data, struct json_object *responseJ, const char *error, const char *info, afb_req_t request) {
    CtlActionT *action = (CtlActionT *) data;

    if (!action) {
        afb_req_fail_f(request,
                       "Action is null, won't be able to handle the response, error=%s info=%s response=%s",
                       error ? error : "NULL",
                       info ? info : "NULL",
                       responseJ ? json_object_get_string(responseJ) : "NULL");
    }
    else if (error) {
        afb_req_fail_f(request,
                       "subcall-fail",
                       "An error happened during verb call, error=%s info=%s uid=%s api=%s verb=%s args=%s response=%s",
                       error ? error : "NULL",
                       info ? info : "NULL",
                       action->uid,
                       action->exec.subcall.api,
                       action->exec.subcall.verb,
                       json_object_get_string(action->argsJ),
                       responseJ ? json_object_get_string(responseJ) : "NULL");
    }
    else {
        afb_req_success(request, responseJ ? json_object_get(responseJ) : NULL, info);
    }
}

void HandleApiCallActionResponseFromEvent(void *data, struct json_object *responseJ, const char *error, const char *info, afb_api_t apiHandle) {
    CtlActionT *action = (CtlActionT *) data;

    if (!action) {
        AFB_API_ERROR(apiHandle,
                      "Action is null, won't be able to handle the response, error=%s info=%s response=%s",
                      error ? error : "NULL",
                      info ? info : "NULL",
                      responseJ ? json_object_get_string(responseJ) : "NULL");
    }
    else if (error) {
        AFB_API_ERROR(apiHandle,
                      "An error happened during verb call, error=%s info=%s uid=%s api=%s verb=%s args=%s response=%s",
                      error ? error : "NULL",
                      info ? info : "NULL",
                      action->uid,
                      action->exec.subcall.api,
                      action->exec.subcall.verb,
                      json_object_get_string(action->argsJ),
                      responseJ ? json_object_get_string(responseJ) : "NULL");
    }
    else {
        AFB_API_DEBUG(apiHandle,
                      "Seems that everything went fine during verb call, error=%s info=%s uid=%s api=%s verb=%s args=%s response=%s",
                      error ? error : "NULL",
                      info ? info : "NULL",
                      action->uid,
                      action->exec.subcall.api,
                      action->exec.subcall.verb,
                      json_object_get_string(action->argsJ),
                      responseJ ? json_object_get_string(responseJ) : "NULL");
    }
}

int ActionExecOne(CtlSourceT *source, CtlActionT* action, json_object *queryJ) {
    int err = 0;

    switch (action->type) {
        case CTL_TYPE_API:
        {
            json_object *extendedQueryJ = NULL;

            if (action->argsJ) {
                switch(json_object_get_type(queryJ)) {
                    case json_type_object: {
                        extendedQueryJ = wrap_json_clone(queryJ);

                        wrap_json_object_add(extendedQueryJ, action->argsJ);
                        break;
                    }

                    case json_type_null:
                        extendedQueryJ = json_object_get(action->argsJ);
                        break;

                    default:
                        AFB_API_ERROR(action->api, "ActionExecOne(queryJ should be an object) uid=%s args=%s", source->uid, json_object_get_string(queryJ));
                        return -1;
                }
            }
            else {
                extendedQueryJ = json_object_get(queryJ);
            }

            /* AFB Subcall will release the json_object doing the json_object_put() call */
            if (!source->request) {
                afb_api_call(action->api,
                             action->exec.subcall.api,
                             action->exec.subcall.verb,
                             extendedQueryJ,
                             &HandleApiCallActionResponseFromEvent,
                             (void *) action);
            }
            else {
                afb_req_subcall(source->request,
                                action->exec.subcall.api,
                                action->exec.subcall.verb,
                                extendedQueryJ,
                                afb_req_subcall_pass_events | afb_req_subcall_on_behalf,
                                &HandleApiCallActionResponseFromVerbCall,
                                (void *) action);
            }
            break;
        }

#ifdef CONTROL_SUPPORT_LUA
        case CTL_TYPE_LUA:
            err = LuaCallFunc(source, action, queryJ);
            if (err) {
                AFB_API_ERROR(action->api, "ActionExecOne(Lua) uid=%s func=%s args=%s", source->uid, action->exec.lua.funcname, json_object_get_string(action->argsJ));
            }
            break;
#endif

        case CTL_TYPE_CB:
            source->plugin = action->exec.cb.plugin;
            err = (*action->exec.cb.callback) (source, action->argsJ, queryJ);
            if (err) {
                AFB_API_ERROR(action->api, "ActionExecOne(Callback) uid%s plugin=%s function=%s args=%s", source->uid, action->exec.cb.plugin->uid, action->exec.cb.funcname, json_object_get_string(action->argsJ));
            }
            break;

        default:
        {
            AFB_API_ERROR(action->api, "ActionExecOne(unknown) API type uid=%s", source->uid);
            break;
        }
    }

    return err;
}


// Direct Request Call in APIV3
static void ActionDynRequest(afb_req_t request) {
    // retrieve action handle from request and execute the request
    json_object *queryJ = afb_req_json(request);
    CtlActionT* action = (CtlActionT*) afb_req_get_vcbdata(request);

    CtlSourceT source;
    source.uid = action->uid;
    source.request = request;
    source.api = action->api;

    // provide request and execute the action
    ActionExecOne(&source, action, queryJ);
}

void ParseURI(const char *uri, char **first, char **second) {
    char *tmp;

    if(! uri || ! first || ! second) {
        return;
    }

    tmp = strdup(uri);
    if (!tmp) {
        *first = NULL;
        *second = NULL;
        return;
    }

    *first = tmp;

    tmp = strchrnul(tmp, '#');
    if(tmp[0] == '\0') {
        *second = NULL;
    }
    else {
        tmp[0] = '\0';
        *second = &tmp[1];
    }
}

/*** This function will fill the CtlActionT pointer given in parameters for a
 * given api using an 'uri' that specify the C plugin to use and the name of
 * the function
 *
 */
static int BuildPluginAction(afb_api_t apiHandle, const char *uri, CtlActionT *action) {
    char *plugin = NULL, *function = NULL;
    json_object *callbackJ = NULL;

    if (!action) {
        AFB_API_ERROR(apiHandle, "Action not valid");
        return -1;
    }

    ParseURI(uri, &plugin, &function);

    action->type = CTL_TYPE_CB;

    if (plugin && function) {
        if (wrap_json_pack(&callbackJ, "{ss,ss,s?o*}",
                "plugin", plugin,
                "function", function,
                "args", action->argsJ)) {
            AFB_API_ERROR(apiHandle, "Error packing Callback JSON object for plugin %s and function %s", uri, function);
            return -1;
        } else {
            return PluginGetCB(apiHandle, action, callbackJ);
        }
    } else {
        AFB_API_ERROR(apiHandle, "Miss something uri or function.");
        return -1;
    }

    return 0;
}

/*** This function will fill the CtlActionT pointer given in parameters for a
 * given api using an 'uri' that specify the API to use and the name of the
 * verb
 *
 * Be aware that 'uri' and 'function' could be null but will result in
 * unexpected result.
 *
 */
static int BuildApiAction(afb_api_t apiHandle, const char *uri, CtlActionT *action) {
    char *api = NULL, *verb = NULL;

    if (!action) {
        AFB_API_ERROR(apiHandle, "Action not valid");
        return -1;
    }

    ParseURI(uri, &api, &verb);

    if(!api || !verb) {
        AFB_API_ERROR(apiHandle, "Error parsing the action string");
        return -1;
    }

    action->type = CTL_TYPE_API;
    action->exec.subcall.api = api;
    action->exec.subcall.verb = verb;

    return 0;
}

/*** This function will fill the CtlActionT pointer given in parameters for a
 * given api using an 'uri' that specify the Lua plugin to use and the name of
 * the function.
 *
 * Be aware that 'uri' and 'function' could be null but will result in
 * unexpected result.
 *
 */
#ifdef CONTROL_SUPPORT_LUA

static int BuildLuaAction(afb_api_t apiHandle, const char *uri, CtlActionT *action) {
    char *plugin = NULL, *function = NULL;

    if (!action) {
        AFB_API_ERROR(apiHandle, "Action not valid");
        return -1;
    }

    ParseURI(uri, &plugin, &function);

    if(!plugin || !function) {
        AFB_API_ERROR(apiHandle, "Error parsing the action string");
        return -1;
    }

    action->type = CTL_TYPE_LUA;
    action->exec.lua.plugin = plugin;
    action->exec.lua.funcname = function;

    return 0;
}
#endif

static int BuildOneAction(afb_api_t apiHandle, CtlActionT *action, const char *uri) {
    size_t lua_pre_len = strlen(LUA_ACTION_PREFIX);
    size_t api_pre_len = strlen(API_ACTION_PREFIX);
    size_t plugin_pre_len = strlen(PLUGIN_ACTION_PREFIX);

    if (uri && action) {
        if (!strncasecmp(uri, LUA_ACTION_PREFIX, lua_pre_len)) {
#ifdef CONTROL_SUPPORT_LUA
            return BuildLuaAction(apiHandle, &uri[lua_pre_len], action);
#else
            AFB_API_ERROR(apiHandle, "LUA support not selected at build. Feature disabled");
            return -1;
#endif
        } else if (!strncasecmp(uri, API_ACTION_PREFIX, api_pre_len)) {
            return BuildApiAction(apiHandle, &uri[api_pre_len], action);
        } else if (!strncasecmp(uri, PLUGIN_ACTION_PREFIX, plugin_pre_len)) {
            return BuildPluginAction(apiHandle, &uri[plugin_pre_len], action);
        } else {
            AFB_API_ERROR(apiHandle, "Wrong uri specified. You have to specified 'lua://', 'plugin://' or 'api://'.");
            return -1;
        }
    }

    AFB_API_ERROR(apiHandle, "Uri, Action or function not valid");
    return -1;
}

// unpack individual action object

int ActionLoadOne(afb_api_t apiHandle, CtlActionT *action, json_object *actionJ, int exportApi) {
    int err = 0;
    const char *uri = NULL;

    memset(action, 0, sizeof (CtlActionT));

    if (actionJ) {
        err = wrap_json_unpack(actionJ, "{ss,s?s,ss,s?s,s?o}",
                "uid", &action->uid,
                "info", &action->info,
                "action", &uri,
                "privileges", &action->privileges,
                "args", &action->argsJ);
        if (!err) {
            if(!apiHandle)
                return -1;
            action->api = apiHandle;
            if (exportApi) {
                err = afb_api_add_verb(apiHandle, action->uid, action->info, ActionDynRequest, action, NULL, 0, 0);
                if (err) {
                    AFB_API_ERROR(apiHandle, "ACTION-LOAD-ONE fail to register API verb=%s", action->uid);
                    return -1;
                }
            }
            err = BuildOneAction(apiHandle, action, uri);
        } else {
            AFB_API_ERROR(apiHandle, "Fail to parse action JSON : (%s)", json_object_to_json_string(actionJ));
            err = -1;
        }
    } else {
        AFB_API_ERROR(apiHandle, "Wrong action JSON object parameter: (%s)", json_object_to_json_string(actionJ));
        err = -1;
    }

    return err;
}

CtlActionT *ActionConfig(afb_api_t apiHandle, json_object *actionsJ, int exportApi) {
    int err;
    CtlActionT *actions;

    // action array is close with a nullvalue;
    if (json_object_is_type(actionsJ, json_type_array)) {
        int count = (int)json_object_array_length(actionsJ);
        actions = calloc(count + 1, sizeof (CtlActionT));

        for (int idx = 0; idx < count; idx++) {
            json_object *actionJ = json_object_array_get_idx(actionsJ, idx);

            err = ActionLoadOne(apiHandle, &actions[idx], actionJ, exportApi);
            if (err)
                return NULL;
        }

    } else {
        actions = calloc(2, sizeof (CtlActionT));
        err = ActionLoadOne(apiHandle, &actions[0], actionsJ, exportApi);
        if (err)
            return NULL;
    }

    return actions;
}

int AddActionsToSection(afb_api_t apiHandle, CtlSectionT *section, json_object *actionsJ, int exportApi) {
    if (actionsJ || section) {
        CtlActionT *actions = NULL;
        if(section->actions) {
            int actionsNb = 0, idx = 0, jdx = 0;
            CtlActionT *savedActions = section->actions;
            CtlActionT *newActions = ActionConfig(apiHandle, actionsJ, exportApi);

            while(savedActions[actionsNb].uid)
                actionsNb++;
            while(newActions[actionsNb].uid)
                actionsNb++;

            actions = calloc(actionsNb + 1, sizeof(CtlActionT));

            while(savedActions[idx].uid) {
                actions[idx] = savedActions[idx];
                idx++;
            }
            while(newActions[jdx].uid && idx <= actionsNb) {
                actions[idx] = newActions[jdx];
                idx++;
                jdx++;
            }
            free(savedActions);
            free(newActions);
        }
        else {
            actions = ActionConfig(apiHandle, actionsJ, exportApi);
        }
        section->actions = actions;
    }
    else {
        AFB_API_ERROR (apiHandle, "Missing actions to add or the section object");
        return 1;
    }

    if (!section->actions) {
        AFB_API_ERROR (apiHandle, "Adding '%s' fails to section %s", json_object_get_string(actionsJ), section->uid);
        return 1;
    }
        return 0;
}