예제 #1
0
/// Set a value in a dict. Objects are recursively expanded into their
/// vimscript equivalents. Passing 'nil' as value deletes the key.
///
/// @param dict The vimscript dict
/// @param key The key
/// @param value The new value
/// @param[out] err Details of an error that may have occurred
/// @return the old value, if any
Object dict_set_value(dict_T *dict, String key, Object value, Error *err)
{
  Object rv = OBJECT_INIT;

  if (dict->dv_lock) {
    api_set_error(err, Exception, _("Dictionary is locked"));
    return rv;
  }

  if (key.size == 0) {
    api_set_error(err, Validation, _("Empty dictionary keys aren't allowed"));
    return rv;
  }

  if (key.size > INT_MAX) {
    api_set_error(err, Validation, _("Key length is too high"));
    return rv;
  }

  dictitem_T *di = dict_find(dict, (uint8_t *)key.data, (int)key.size);

  if (value.type == kObjectTypeNil) {
    // Delete the key
    if (di == NULL) {
      // Doesn't exist, fail
      api_set_error(err, Validation, _("Key \"%s\" doesn't exist"), key.data);
    } else {
      // Return the old value
      rv = vim_to_object(&di->di_tv);
      // Delete the entry
      hashitem_T *hi = hash_find(&dict->dv_hashtab, di->di_key);
      hash_remove(&dict->dv_hashtab, hi);
      dictitem_free(di);
    }
  } else {
    // Update the key
    typval_T tv;

    // Convert the object to a vimscript type in the temporary variable
    if (!object_to_vim(value, &tv, err)) {
      return rv;
    }

    if (di == NULL) {
      // Need to create an entry
      di = dictitem_alloc((uint8_t *) key.data);
      dict_add(dict, di);
    } else {
      // Return the old value
      clear_tv(&di->di_tv);
    }

    // Update the value
    copy_tv(&tv, &di->di_tv);
    // Clear the temporary variable
    clear_tv(&tv);
  }

  return rv;
}
예제 #2
0
static Object remote_ui_attach(uint64_t channel_id, uint64_t request_id,
                               Array args, Error *error)
{
  if (pmap_has(uint64_t)(connected_uis, channel_id)) {
    api_set_error(error, Exception, _("UI already attached for channel"));
    return NIL;
  }

  if (args.size != 3 || args.items[0].type != kObjectTypeInteger
      || args.items[1].type != kObjectTypeInteger
      || args.items[2].type != kObjectTypeBoolean
      || args.items[0].data.integer <= 0 || args.items[1].data.integer <= 0) {
    api_set_error(error, Validation,
                  _("Invalid arguments. Expected: "
                    "(uint width > 0, uint height > 0, bool enable_rgb)"));
    return NIL;
  }
  UIData *data = xmalloc(sizeof(UIData));
  data->channel_id = channel_id;
  data->buffer = (Array)ARRAY_DICT_INIT;
  UI *ui = xcalloc(1, sizeof(UI));
  ui->width = (int)args.items[0].data.integer;
  ui->height = (int)args.items[1].data.integer;
  ui->rgb = args.items[2].data.boolean;
  ui->data = data;
  ui->resize = remote_ui_resize;
  ui->clear = remote_ui_clear;
  ui->eol_clear = remote_ui_eol_clear;
  ui->cursor_goto = remote_ui_cursor_goto;
  ui->busy_start = remote_ui_busy_start;
  ui->busy_stop = remote_ui_busy_stop;
  ui->mouse_on = remote_ui_mouse_on;
  ui->mouse_off = remote_ui_mouse_off;
  ui->insert_mode = remote_ui_insert_mode;
  ui->normal_mode = remote_ui_normal_mode;
  ui->set_scroll_region = remote_ui_set_scroll_region;
  ui->scroll = remote_ui_scroll;
  ui->highlight_set = remote_ui_highlight_set;
  ui->put = remote_ui_put;
  ui->bell = remote_ui_bell;
  ui->visual_bell = remote_ui_visual_bell;
  ui->update_fg = remote_ui_update_fg;
  ui->update_bg = remote_ui_update_bg;
  ui->flush = remote_ui_flush;
  ui->suspend = remote_ui_suspend;
  ui->set_title = remote_ui_set_title;
  ui->set_icon = remote_ui_set_icon;
  pmap_put(uint64_t)(connected_uis, channel_id, ui);
  ui_attach(ui);
  return NIL;
}
예제 #3
0
/// Gets the value of a global or local(buffer, window) option.
///
/// @param from If `type` is `SREQ_WIN` or `SREQ_BUF`, this must be a pointer
///        to the window or buffer.
/// @param type One of `SREQ_GLOBAL`, `SREQ_WIN` or `SREQ_BUF`
/// @param name The option name
/// @param[out] err Details of an error that may have occurred
/// @return the option value
Object get_option_from(void *from, int type, String name, Error *err)
{
  Object rv = OBJECT_INIT;

  if (name.size == 0) {
    api_set_error(err, Validation, _("Empty option name"));
    return rv;
  }

  // Return values
  int64_t numval;
  char *stringval = NULL;
  int flags = get_option_value_strict(name.data, &numval, &stringval,
                                      type, from);

  if (!flags) {
    api_set_error(err,
                  Validation,
                  _("Invalid option name \"%s\""),
                  name.data);
    return rv;
  }

  if (flags & SOPT_BOOL) {
    rv.type = kObjectTypeBoolean;
    rv.data.boolean = numval ? true : false;
  } else if (flags & SOPT_NUM) {
    rv.type = kObjectTypeInteger;
    rv.data.integer = numval;
  } else if (flags & SOPT_STRING) {
    if (stringval) {
      rv.type = kObjectTypeString;
      rv.data.string.data = stringval;
      rv.data.string.size = strlen(stringval);
    } else {
      api_set_error(err,
                    Exception,
                    _("Unable to get value for option \"%s\""),
                    name.data);
    }
  } else {
    api_set_error(err,
                  Exception,
                  _("Unknown type for option \"%s\""),
                  name.data);
  }

  return rv;
}
예제 #4
0
파일: ui.c 프로젝트: KillTheMule/neovim
void ui_grid_resize(handle_T grid_handle, int width, int height, Error *error)
{
  if (grid_handle == DEFAULT_GRID_HANDLE) {
    screen_resize(width, height);
    return;
  }

  win_T *wp = get_win_by_grid_handle(grid_handle);
  if (wp == NULL) {
    api_set_error(error, kErrorTypeValidation,
                  "No window with the given handle");
    return;
  }

  if (wp->w_floating) {
    if (width != wp->w_width && height != wp->w_height) {
      wp->w_float_config.width = width;
      wp->w_float_config.height = height;
      win_config_float(wp, wp->w_float_config);
    }
  } else {
    // non-positive indicates no request
    wp->w_height_request = (int)MAX(height, 0);
    wp->w_width_request = (int)MAX(width, 0);
    win_set_inner_size(wp);
  }
}
예제 #5
0
파일: ui.c 프로젝트: alecbrooks/neovim
static void ui_set_option(UI *ui, bool init, String name, Object value,
                          Error *error)
{
  if (strequal(name.data, "rgb")) {
    if (value.type != kObjectTypeBoolean) {
      api_set_error(error, kErrorTypeValidation, "rgb must be a Boolean");
      return;
    }
    ui->rgb = value.data.boolean;
    // A little drastic, but only legacy uis need to use this option
    if (!init) {
      ui_refresh();
    }
    return;
  }

  // LEGACY: Deprecated option, use `ext_cmdline` instead.
  bool is_popupmenu = strequal(name.data, "popupmenu_external");

  for (UIExtension i = 0; i < kUIExtCount; i++) {
    if (strequal(name.data, ui_ext_names[i])
        || (i == kUIPopupmenu && is_popupmenu)) {
      if (value.type != kObjectTypeBoolean) {
        snprintf((char *)IObuff, IOSIZE, "%s must be a Boolean",
                 name.data);
        api_set_error(error, kErrorTypeValidation, (char *)IObuff);
        return;
      }
      bool boolval = value.data.boolean;
      if (!init && i == kUINewgrid && boolval != ui->ui_ext[i]) {
        // There shouldn't be a reason for an UI to do this ever
        // so explicitly don't support this.
        api_set_error(error, kErrorTypeValidation,
                      "ext_newgrid option cannot be changed");
      }
      ui->ui_ext[i] = boolval;
      if (!init) {
        ui_set_ext_option(ui, i, boolval);
      }
      return;
    }
  }

  api_set_error(error, kErrorTypeValidation, "No such UI option: %s",
                name.data);
}
예제 #6
0
파일: vim.c 프로젝트: DINKIN/neovim
/// Calculates the number of display cells `str` occupies, tab is counted as
/// one cell.
///
/// @param str Some text
/// @param[out] err Details of an error that may have occurred
/// @return The number of cells
Integer vim_strwidth(String str, Error *err)
{
  if (str.size > INT_MAX) {
    api_set_error(err, Validation, _("String length is too high"));
    return 0;
  }

  return (Integer) mb_string2cells((char_u *) str.data);
}
예제 #7
0
파일: ui.c 프로젝트: fatbird/neovim
static void ui_set_option(UI *ui, String name, Object value, Error *error) {
  if (strcmp(name.data, "rgb") == 0) {
    if (value.type != kObjectTypeBoolean) {
      api_set_error(error, Validation, _("rgb must be a Boolean"));
      return;
    }
    ui->rgb = value.data.boolean;
  } else if (strcmp(name.data, "popupmenu_external") == 0) {
    if (value.type != kObjectTypeBoolean) {
      api_set_error(error, Validation,
                    _("popupmenu_external must be a Boolean"));
      return;
    }
    ui->pum_external = value.data.boolean;
  } else {
    api_set_error(error, Validation, _("No such ui option"));
  }
}
예제 #8
0
tabpage_T * find_tab_by_handle(Tabpage tabpage, Error *err)
{
  tabpage_T *rv = handle_get_tabpage(tabpage);

  if (!rv) {
    api_set_error(err, Validation, _("Invalid tabpage id"));
  }

  return rv;
}
예제 #9
0
win_T * find_window_by_handle(Window window, Error *err)
{
  win_T *rv = handle_get_window(window);

  if (!rv) {
    api_set_error(err, Validation, _("Invalid window id"));
  }

  return rv;
}
예제 #10
0
buf_T *find_buffer_by_handle(Buffer buffer, Error *err)
{
  buf_T *rv = handle_get_buffer(buffer);

  if (!rv) {
    api_set_error(err, Validation, _("Invalid buffer id"));
  }

  return rv;
}
예제 #11
0
static Object remote_ui_detach(uint64_t channel_id, uint64_t request_id,
                               Array args, Error *error)
{
  if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
    api_set_error(error, Exception, _("UI is not attached for channel"));
  }
  remote_ui_disconnect(channel_id);

  return NIL;
}
예제 #12
0
파일: api_common.c 프로젝트: neufbox/misc
void api_dispatch( void )
{
    api_method_t *m = NULL;
    char *uri = NULL;
    char *name = NULL;

    api_set_value( "version", "1.0" );
    api_set_value( "env.uname", BOXNAME);

    ewf_fastcgi_set_content_type( "text/xml" );

    uri = ewf_http_request_uri(  );
    if ( uri == NULL ) {
	nbu_log_info( "uri is NULL" );
	api_set_error( API_ERROR_METHOD_NOT_FOUND );
	ewf_fastcgi_display( "api/generic.xml" );
	return;
    }

/*        nbu_log_debug("uri: '%s'", uri); */
/*        nbu_log_debug("Query.Method: '%s'", hdf_get_valuef(cgi->hdf, "Query.method")); */
/*        nbu_log_debug("CGI.QueryString: '%s'", hdf_get_valuef(cgi->hdf, "CGI.QueryString")); */
       
    if ( ewf_fastcgi_get_parameter( "method", &name ) == EWF_ERROR ) {
	nbu_log_info( "method param is NULL" );
	api_set_error( API_ERROR_METHOD_NOT_FOUND );
	ewf_fastcgi_display( "api/generic.xml" );
	return;
    }

    if ( ewf_hashtable_find( &methods.list, name, ( void * ) &m ) == EWF_ERROR ) {
	nbu_log_info( "method '%s' not found", name );
	api_set_error( API_ERROR_METHOD_NOT_FOUND );
	ewf_fastcgi_display( "api/generic.xml" );
	return;
    }

    nbu_log_info( "method '%s' found", name );
    api_handle_request( m, name );

    return;
}
예제 #13
0
파일: vim.c 프로젝트: DINKIN/neovim
/// Call the given function with the given arguments stored in an array.
///
/// @param fname Function to call
/// @param args Functions arguments packed in an Array
/// @param[out] err Details of an error that may have occurred
/// @return Result of the function call
Object vim_call_function(String fname, Array args, Error *err)
{
  Object rv = OBJECT_INIT;
  if (args.size > MAX_FUNC_ARGS) {
    api_set_error(err, Validation,
      _("Function called with too many arguments."));
    return rv;
  }

  // Convert the arguments in args from Object to typval_T values
  typval_T vim_args[MAX_FUNC_ARGS + 1];
  size_t i = 0;  // also used for freeing the variables
  for (; i < args.size; i++) {
    if (!object_to_vim(args.items[i], &vim_args[i], err)) {
      goto free_vim_args;
    }
  }

  try_start();
  // Call the function
  typval_T rettv;
  int dummy;
  int r = call_func((char_u *) fname.data, (int) fname.size,
                    &rettv, (int) args.size, vim_args,
                    curwin->w_cursor.lnum, curwin->w_cursor.lnum, &dummy,
                    true,
                    NULL);
  if (r == FAIL) {
    api_set_error(err, Exception, _("Error calling function."));
  }
  if (!try_end(err)) {
    rv = vim_to_object(&rettv);
  }
  clear_tv(&rettv);

free_vim_args:
  while (i > 0) {
    clear_tv(&vim_args[--i]);
  }

  return rv;
}
예제 #14
0
/// Recursively expands a vimscript value in a dict
///
/// @param dict The vimscript dict
/// @param key The key
/// @param[out] err Details of an error that may have occurred
Object dict_get_value(dict_T *dict, String key, Error *err)
{
  hashitem_T *hi = hash_find(&dict->dv_hashtab, (uint8_t *) key.data);

  if (HASHITEM_EMPTY(hi)) {
    api_set_error(err, Validation, _("Key not found"));
    return (Object) OBJECT_INIT;
  }

  dictitem_T *di = dict_lookup(hi);
  return vim_to_object(&di->di_tv);
}
예제 #15
0
static Object remote_ui_try_resize(uint64_t channel_id, uint64_t request_id,
                                   Array args, Error *error)
{
  if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
    api_set_error(error, Exception, _("UI is not attached for channel"));
  }

  if (args.size != 2 || args.items[0].type != kObjectTypeInteger
      || args.items[1].type != kObjectTypeInteger
      || args.items[0].data.integer <= 0 || args.items[1].data.integer <= 0) {
    api_set_error(error, Validation,
                  _("Invalid arguments. Expected: "
                    "(uint width > 0, uint height > 0)"));
    return NIL;
  }

  UI *ui = pmap_get(uint64_t)(connected_uis, channel_id);
  ui->width = (int)args.items[0].data.integer;
  ui->height = (int)args.items[1].data.integer;
  ui_refresh();
  return NIL;
}
예제 #16
0
파일: vim.c 프로젝트: DINKIN/neovim
/// Changes Vim working directory
///
/// @param dir The new working directory
/// @param[out] err Details of an error that may have occurred
void vim_change_directory(String dir, Error *err)
{
  if (dir.size >= MAXPATHL) {
    api_set_error(err, Validation, _("Directory string is too long"));
    return;
  }

  char string[MAXPATHL];
  strncpy(string, dir.data, dir.size);
  string[dir.size] = NUL;

  try_start();

  if (vim_chdir((char_u *)string)) {
    if (!try_end(err)) {
      api_set_error(err, Exception, _("Failed to change directory"));
    }
    return;
  }

  post_chdir(kCdScopeGlobal);
  try_end(err);
}
예제 #17
0
파일: helpers.c 프로젝트: logtcn/neovim
/// End try block, set the error message if any and return true if an error
/// occurred.
///
/// @param err Pointer to the stack-allocated error object
/// @return true if an error occurred
bool try_end(Error *err)
{
    --trylevel;

    // Without this it stops processing all subsequent VimL commands and
    // generates strange error messages if I e.g. try calling Test() in a
    // cycle
    did_emsg = false;

    if (got_int) {
        if (did_throw) {
            // If we got an interrupt, discard the current exception
            discard_current_exception();
        }

        api_set_error(err, Exception, _("Keyboard interrupt"));
        got_int = false;
    } else if (msg_list != NULL && *msg_list != NULL) {
        int should_free;
        char *msg = (char *)get_exception_string(*msg_list,
                    ET_ERROR,
                    NULL,
                    &should_free);
        xstrlcpy(err->msg, msg, sizeof(err->msg));
        err->set = true;
        free_global_msglist();

        if (should_free) {
            xfree(msg);
        }
    } else if (did_throw) {
        api_set_error(err, Exception, "%s", current_exception->value);
        discard_current_exception();
    }

    return err->set;
}
예제 #18
0
파일: wlan.c 프로젝트: neufbox/misc
API_REGISTER_METHOD( wlan, setWlanMode, EWF_HTTP_REQUEST_METHOD_POST, API_ACCESS_POLICY_PRIVATE )
{
	char *param = NULL;
        int ret;

	if ( ewf_fastcgi_get_parameter( "mode", &param ) == EWF_SUCCESS 
             && (ret = cfg_set("wlan_mode", param)) >= cfg_set_success) 
	{
                if(ret == cfg_set_success)
                {
                        nbd_nv_commit( "user" );
                }
	}
        else
        {
                api_set_error(API_ERROR_INVALID_ARG);
        }
}
예제 #19
0
파일: vim.c 프로젝트: DINKIN/neovim
/// Evaluates the expression str using the Vim internal expression
/// evaluator (see |expression|).
/// Dictionaries and lists are recursively expanded.
///
/// @param str The expression str
/// @param[out] err Details of an error that may have occurred
/// @return The expanded object
Object vim_eval(String str, Error *err)
{
  Object rv = OBJECT_INIT;
  // Evaluate the expression
  try_start();
  typval_T *expr_result = eval_expr((char_u *) str.data, NULL);

  if (!expr_result) {
    api_set_error(err, Exception, _("Failed to evaluate expression"));
  }

  if (!try_end(err)) {
    // No errors, convert the result
    rv = vim_to_object(expr_result);
  }

  // Free the vim object
  free_tv(expr_result);
  return rv;
}
예제 #20
0
/// Sets the value of a global or local(buffer, window) option.
///
/// @param to If `type` is `SREQ_WIN` or `SREQ_BUF`, this must be a pointer
///        to the window or buffer.
/// @param type One of `SREQ_GLOBAL`, `SREQ_WIN` or `SREQ_BUF`
/// @param name The option name
/// @param[out] err Details of an error that may have occurred
void set_option_to(void *to, int type, String name, Object value, Error *err)
{
  if (name.size == 0) {
    api_set_error(err, Validation, _("Empty option name"));
    return;
  }

  int flags = get_option_value_strict(name.data, NULL, NULL, type, to);

  if (flags == 0) {
    api_set_error(err,
                  Validation,
                  _("Invalid option name \"%s\""),
                  name.data);
    return;
  }

  if (value.type == kObjectTypeNil) {
    if (type == SREQ_GLOBAL) {
      api_set_error(err,
                    Exception,
                    _("Unable to unset option \"%s\""),
                    name.data);
      return;
    } else if (!(flags & SOPT_GLOBAL)) {
      api_set_error(err,
                    Exception,
                    _("Cannot unset option \"%s\" "
                      "because it doesn't have a global value"),
                    name.data);
      return;
    } else {
      unset_global_local_option(name.data, to);
      return;
    }
  }

  int opt_flags = (type ? OPT_LOCAL : OPT_GLOBAL);

  if (flags & SOPT_BOOL) {
    if (value.type != kObjectTypeBoolean) {
      api_set_error(err,
                    Validation,
                    _("Option \"%s\" requires a boolean value"),
                    name.data);
      return;
    }

    bool val = value.data.boolean;
    set_option_value_for(name.data, val, NULL, opt_flags, type, to, err);
  } else if (flags & SOPT_NUM) {
    if (value.type != kObjectTypeInteger) {
      api_set_error(err,
                    Validation,
                    _("Option \"%s\" requires an integer value"),
                    name.data);
      return;
    }

    if (value.data.integer > INT_MAX || value.data.integer < INT_MIN) {
      api_set_error(err,
                    Validation,
                    _("Value for option \"%s\" is outside range"),
                    name.data);
      return;
    }

    int val = (int) value.data.integer;
    set_option_value_for(name.data, val, NULL, opt_flags, type, to, err);
  } else {
    if (value.type != kObjectTypeString) {
      api_set_error(err,
                    Validation,
                    _("Option \"%s\" requires a string value"),
                    name.data);
      return;
    }

    set_option_value_for(name.data, 0, value.data.string.data,
            opt_flags, type, to, err);
  }
}
예제 #21
0
/// Copies a C string into a String (binary safe string, characters + length).
/// The resulting string is also NUL-terminated, to facilitate interoperating
/// with code using C strings.
///
/// @param str the C string to copy
/// @return the resulting String, if the input string was NULL, an
///         empty String is returned
String cstr_to_string(const char *str)
{
    if (str == NULL) {
        return (String) STRING_INIT;
    }

    size_t len = strlen(str);
    return (String) {
        .data = xmemdupz(str, len),
        .size = len
    };
}

/// Creates a String using the given C string. Unlike
/// cstr_to_string this function DOES NOT copy the C string.
///
/// @param str the C string to use
/// @return The resulting String, or an empty String if
///           str was NULL
String cstr_as_string(char *str) FUNC_ATTR_PURE
{
  if (str == NULL) {
    return (String) STRING_INIT;
  }
  return (String) {.data = str, .size = strlen(str)};
}

bool object_to_vim(Object obj, typval_T *tv, Error *err)
{
  tv->v_type = VAR_UNKNOWN;
  tv->v_lock = 0;

  switch (obj.type) {
    case kObjectTypeNil:
      tv->v_type = VAR_NUMBER;
      tv->vval.v_number = 0;
      break;

    case kObjectTypeBoolean:
      tv->v_type = VAR_NUMBER;
      tv->vval.v_number = obj.data.boolean;
      break;

    case kObjectTypeInteger:
      if (obj.data.integer > INT_MAX || obj.data.integer < INT_MIN) {
        api_set_error(err, Validation, _("Integer value outside range"));
        return false;
      }

      tv->v_type = VAR_NUMBER;
      tv->vval.v_number = (int)obj.data.integer;
      break;

    case kObjectTypeFloat:
      tv->v_type = VAR_FLOAT;
      tv->vval.v_float = obj.data.floating;
      break;

    case kObjectTypeString:
      tv->v_type = VAR_STRING;
      tv->vval.v_string = xmemdupz(obj.data.string.data,
                                   obj.data.string.size);
      break;

    case kObjectTypeArray:
      tv->v_type = VAR_LIST;
      tv->vval.v_list = list_alloc();

      for (uint32_t i = 0; i < obj.data.array.size; i++) {
        Object item = obj.data.array.items[i];
        listitem_T *li = listitem_alloc();

        if (!object_to_vim(item, &li->li_tv, err)) {
          // cleanup
          listitem_free(li);
          list_free(tv->vval.v_list, true);
          return false;
        }

        list_append(tv->vval.v_list, li);
      }
      tv->vval.v_list->lv_refcount++;
      break;

    case kObjectTypeDictionary:
      tv->v_type = VAR_DICT;
      tv->vval.v_dict = dict_alloc();

      for (uint32_t i = 0; i < obj.data.dictionary.size; i++) {
        KeyValuePair item = obj.data.dictionary.items[i];
        String key = item.key;

        if (key.size == 0) {
          api_set_error(err,
                        Validation,
                        _("Empty dictionary keys aren't allowed"));
          // cleanup
          dict_free(tv->vval.v_dict, true);
          return false;
        }

        dictitem_T *di = dictitem_alloc((uint8_t *) key.data);

        if (!object_to_vim(item.value, &di->di_tv, err)) {
          // cleanup
          dictitem_free(di);
          dict_free(tv->vval.v_dict, true);
          return false;
        }

        dict_add(tv->vval.v_dict, di);
      }
      tv->vval.v_dict->dv_refcount++;
      break;
    default:
      abort();
  }

  return true;
}
예제 #22
0
파일: api_common.c 프로젝트: neufbox/misc
void api_handle_request( api_method_t * m, const char *name )
{
    ewf_http_request_method_t reqm;
    ewf_session_t* session = NULL;
    char *token = NULL, *c_stat = NULL;
    int have_authoriz = 0, have_error = 0, ret = 0;
    char buf[64];

    /* method struct must be initialized */
    if ( m == NULL ) {
	nbu_log_info( "method struct is NULL" );
	api_set_error( API_ERROR_METHOD_NOT_FOUND );
	ewf_fastcgi_display( "api/generic.xml" );
	return;
    }

    /* test if method exist */
    reqm = ewf_http_request_method(  );
    if ( reqm != m->request_method ) {
	nbu_log_info
	    ( "request method is wrong: got '%d', should be '%d'", reqm, m->request_method );
	api_set_error( API_ERROR_METHOD_NOT_FOUND );
	ewf_fastcgi_display( "api/generic.xml" );
	return;
    }

    /* action handler is defined ? */
    if ( m->action_handler == NULL ) {
	nbu_log_info( "action handler is NULL" );
	api_set_error( API_ERROR_METHOD_NOT_FOUND );
	ewf_fastcgi_display( "api/generic.xml" );
	return;
    }

    /* the box being upgrade ? */
        ret = nbd_autoconf_get("status", buf, sizeof(buf));
	if (ret == NBD_SUCCESS)
	{
		if(strncmp("downloading", buf, 11) == 0)
		{
			nbu_log_info( "The box is being upgrade ..." );
			api_set_error( API_ERROR_BOX_UPGRADING );
			ewf_fastcgi_display( "api/generic.xml" );
			ret = NBU_SUCCESS;
		}
	}
    
	/* if method is a POST method, parse POST arguments */
    if ( reqm == EWF_HTTP_REQUEST_METHOD_POST ) {
	ewf_fastcgi_parse(  );
    }

    /* check auth if method is private */
    if(m->access_policy == API_ACCESS_POLICY_PRIVATE)
    {
	    nbu_log_debug( "method '%s' is private !", name );
            
            /* maybe, api authentification is desactivated ? */
            if(nbd_nv_get("web_auth", buf, sizeof(buf)) == NBD_SUCCESS
               && nbu_string_matches(buf, "off") == NBU_STRING_EQUAL)
            {
                    nbu_log_debug( "api auth is desactivated" );
                    have_authoriz = 1;
            }
            else
            {
                    /* check token */
                    if(ewf_fastcgi_get_parameter("token", &token) != EWF_SUCCESS)
                    {
                            /* no token submit, return need auth ! */
                            api_set_error(API_ERROR_NEED_AUTH);
                    }
                    else
                    {
                            /* token is here, try to get session */
                            nbu_log_debug("Token is here ! %s", token);
                            if(ewf_session_get(token, &session) != EWF_SUCCESS)
                            {
                                    /* no session found ! */
                                    api_set_error(API_ERROR_NEED_AUTH);
                            }
                            else
                            {
                                    nbu_log_debug("Token is good !");
			    
                                    /* verify that session is valid and if the case, update it ! */
                                    if(ewf_session_check(session) != EWF_SUCCESS)
                                    {
                                            /* invalid session */
                                            api_set_error(API_ERROR_NEED_AUTH);
                                    }
                                    else
                                    {
                                            /* authentified ! */
                                            nbu_log_debug("User allowed to access private method");
                                            have_authoriz = 1;
                                    }
                            }
                    }
            }
    }
    else
    {
	    /* public method can be acceeded by anyone */
	    have_authoriz = 1;
    }
    
    if(!have_authoriz)
    {
	    have_error = 1;
    }
    else
    {
	    m->action_handler(  );
	    
	    /* check if an error has "throw" in the action method */
	    if((c_stat = hdf_get_value(cgi->hdf, "stat", NULL)) != NULL && nbu_string_compare(c_stat, "fail") == NBU_STRING_EQUAL)
	    {
		    have_error = 1;
	    }
	    else
	    {
		    if ( reqm == EWF_HTTP_REQUEST_METHOD_GET ) 
		    {
			    nbu_string_printf( buffer, sizeof buffer, "api/%s.%s", name, "xml" );
		    }
		    else 
		    {
			    /* display ok msg with generic xml template */
			    nbu_string_printf( buffer, sizeof buffer, "api/%s.%s", "generic", "xml" );
		    }
		    
		    api_set_value( "stat", "ok" );
	    }
    }
    
    if(have_error)
    {
	    /* display error with generic xml template */
	    nbu_string_printf( buffer, sizeof buffer, "api/%s.%s", "generic", "xml" );
    }

    ewf_fastcgi_display( buffer );

    return;
}