/**
 *
 * Glewlwyd SSO Server
 *
 * Authentiation server
 * Users are authenticated via various backend available: database, ldap
 * Using various authentication methods available: password, OTP, send code, etc.
 * 
 * client management functions definition
 *
 * Copyright 2016-2021 Nicolas Mora <mail@babelouest.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU GENERAL PUBLIC LICENSE
 * License as published by the Free Software Foundation;
 * version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU GENERAL PUBLIC LICENSE for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
#include "glewlwyd.h"

json_t * auth_check_client_credentials(struct config_elements * config, const char * client_id, const char * password) {
  int res;
  json_t * j_return = NULL, * j_module_list = get_client_module_list(config), * j_module, * j_client;
  struct _client_module_instance * client_module;
  size_t index;
  
  if (check_result_value(j_module_list, G_OK)) {
    json_array_foreach(json_object_get(j_module_list, "module"), index, j_module) {
      if ((res = is_client_backend_api_run_enabled(config, json_string_value(json_object_get(j_module, "name")))) == G_OK) {
        if (j_return == NULL) {
          client_module = get_client_module_instance(config, json_string_value(json_object_get(j_module, "name")));
          if (client_module != NULL) {
            if (client_module->enabled) {
              j_client = client_module->module->client_module_get(config->config_m, client_id, client_module->cls);
              if (check_result_value(j_client, G_OK)) {
                res = client_module->module->client_module_check_password(config->config_m, client_id, password, client_module->cls);
                if (res == G_OK) {
                  j_return = json_pack("{si}", "result", G_OK);
                } else if (res == G_ERROR_UNAUTHORIZED) {
                  j_return = json_pack("{si}", "result", G_ERROR_UNAUTHORIZED);
                } else if (res != G_ERROR_NOT_FOUND) {
                  y_log_message(Y_LOG_LEVEL_ERROR, "auth_check_client_credentials - Error, client_module_check_password for module '%s', skip", client_module->name);
                }
              } else if (!check_result_value(j_client, G_ERROR_NOT_FOUND)) {
                y_log_message(Y_LOG_LEVEL_ERROR, "auth_check_client_credentials - Error, client_module_get for module '%s', skip", client_module->name);
              }
              json_decref(j_client);
            }
          } else {
            y_log_message(Y_LOG_LEVEL_ERROR, "auth_check_client_credentials - Error, client_module_instance %s is NULL", json_string_value(json_object_get(j_module, "name")));
          }
        }
      } else if (res != G_ERROR_NOT_FOUND) {
        y_log_message(Y_LOG_LEVEL_ERROR, "auth_check_client_credentials - Error is_client_backend_api_run_enabled");
      }
    }
  } else {
    y_log_message(Y_LOG_LEVEL_ERROR, "auth_check_client_credentials - Error get_client_module_list");
    j_return = json_pack("{si}", "result", G_ERROR);
  }
  json_decref(j_module_list);
  if (j_return == NULL) {
    j_return = json_pack("{si}", "result", G_ERROR_UNAUTHORIZED);
  }
  return j_return;
}

json_t * get_client(struct config_elements * config, const char * client_id, const char * source) {
  int found = 0, res;
  json_t * j_return = NULL, * j_client, * j_module_list, * j_module;
  struct _client_module_instance * client_module;
  size_t index;
  
  if (o_strnullempty(client_id)) {
    j_return = json_pack("{si}", "result", G_ERROR_PARAM);
  } else if (source != NULL) {
    if ((res = is_client_backend_api_run_enabled(config, source)) == G_OK) {
      client_module = get_client_module_instance(config, source);
      if (client_module != NULL) {
        j_client = client_module->module->client_module_get(config->config_m, client_id, client_module->cls);
        if (check_result_value(j_client, G_OK)) {
          json_object_set_new(json_object_get(j_client, "client"), "source", json_string(source));
          j_return = json_incref(j_client);
        } else if (check_result_value(j_client, G_ERROR_NOT_FOUND)) {
          j_return = json_pack("{si}", "result", G_ERROR_NOT_FOUND);
        } else {
          y_log_message(Y_LOG_LEVEL_ERROR, "get_client - Error, client_module_get for module %s", client_module->name);
          j_return = json_pack("{si}", "result", G_ERROR);
        }
        json_decref(j_client);
      } else {
        j_return = json_pack("{si}", "result", G_ERROR_NOT_FOUND);
      }
    } else if (res != G_ERROR_NOT_FOUND) {
      y_log_message(Y_LOG_LEVEL_ERROR, "get_client - Error is_client_backend_api_run_enabled (1)");
      j_return = json_pack("{si}", "result", G_ERROR);
    } else {
      j_return = json_pack("{si}", "result", G_ERROR_NOT_FOUND);
    }
  } else {
    j_module_list = get_client_module_list(config);
    if (check_result_value(j_module_list, G_OK)) {
      json_array_foreach(json_object_get(j_module_list, "module"), index, j_module) {
        if ((res = is_client_backend_api_run_enabled(config, json_string_value(json_object_get(j_module, "name")))) == G_OK) {
          if (!found) {
            client_module = get_client_module_instance(config, json_string_value(json_object_get(j_module, "name")));
            if (client_module != NULL) {
              if (client_module->enabled) {
                j_client = client_module->module->client_module_get(config->config_m, client_id, client_module->cls);
                if (check_result_value(j_client, G_OK)) {
                  json_object_set_new(json_object_get(j_client, "client"), "source", json_string(client_module->name));
                  j_return = json_incref(j_client);
                  found = 1;
                } else if (!check_result_value(j_client, G_ERROR_NOT_FOUND)) {
                  y_log_message(Y_LOG_LEVEL_ERROR, "get_client - Error, client_module_get for module %s", client_module->name);
                  j_return = json_pack("{si}", "result", G_ERROR);
                }
                json_decref(j_client);
              }
            } else {
              y_log_message(Y_LOG_LEVEL_ERROR, "get_client - Error, client_module_instance %s is NULL", json_string_value(json_object_get(j_module, "name")));
            }
          }
        } else if (res != G_ERROR_NOT_FOUND) {
          y_log_message(Y_LOG_LEVEL_ERROR, "get_client - Error is_client_backend_api_run_enabled (2)");
        }
      }
    } else {
      y_log_message(Y_LOG_LEVEL_ERROR, "get_client - Error get_client_module_list");
      j_return = json_pack("{si}", "result", G_ERROR);
    }
    json_decref(j_module_list);
  }
  if (j_return == NULL) {
    j_return = json_pack("{si}", "result", G_ERROR_NOT_FOUND);
  }
  return j_return;
}

json_t * get_client_list(struct config_elements * config, const char * pattern, size_t offset, size_t limit, const char * source) {
  json_t * j_return, * j_module_list, * j_module, * j_list_parsed, * j_element;
  struct _client_module_instance * client_module;
  int result, res;
  size_t cur_offset, cur_limit, count_total, index, index_c;
  
  if (source != NULL) {
    if ((res = is_client_backend_api_run_enabled(config, source)) == G_OK) {
      client_module = get_client_module_instance(config, source);
      if (client_module != NULL && client_module->enabled) {
        result = G_ERROR;
        j_list_parsed = client_module->module->client_module_get_list(config->config_m, pattern, offset, limit, client_module->cls);
        if (check_result_value(j_list_parsed, G_OK)) {
          json_array_foreach(json_object_get(j_list_parsed, "list"), index, j_element) {
            json_object_set_new(j_element, "source", json_string(client_module->name));
          }
          j_return = json_pack("{sisO}", "result", G_OK, "client", json_object_get(j_list_parsed, "list"));
        } else {
          y_log_message(Y_LOG_LEVEL_ERROR, "get_client_list - Error client_module_get_list");
          j_return = json_pack("{si}", "result", result);
        }
        json_decref(j_list_parsed);
      } else if (client_module != NULL && !client_module->enabled) {
        j_return = json_pack("{si}", "result", G_ERROR_PARAM);
      } else {
        y_log_message(Y_LOG_LEVEL_ERROR, "get_client_list - Error get_client_module_instance");
        j_return = json_pack("{si}", "result", G_ERROR);
      }
    } else if (res != G_ERROR_NOT_FOUND) {
      y_log_message(Y_LOG_LEVEL_ERROR, "get_client_list - Error is_client_backend_api_run_enabled (1)");
      j_return = json_pack("{si}", "result", G_ERROR);
    } else {
      j_return = json_pack("{si}", "result", G_ERROR_NOT_FOUND);
    }
  } else {
    j_module_list = get_client_module_list(config);
    if (check_result_value(j_module_list, G_OK)) {
      cur_offset = offset;
      cur_limit = limit;
      j_return = json_pack("{sis[]}", "result", G_OK, "client");
      if (j_return != NULL) {
        json_array_foreach(json_object_get(j_module_list, "module"), index, j_module) {
          if ((res = is_client_backend_api_run_enabled(config, json_string_value(json_object_get(j_module, "name")))) == G_OK) {
            if (cur_limit) {
              client_module = get_client_module_instance(config, json_string_value(json_object_get(j_module, "name")));
              if (client_module != NULL && client_module->enabled) {
                result = G_ERROR;
                if ((count_total = client_module->module->client_module_count_total(config->config_m, pattern, client_module->cls)) > cur_offset && cur_limit) {
                  j_list_parsed = client_module->module->client_module_get_list(config->config_m, pattern, cur_offset, cur_limit, client_module->cls);
                  if (check_result_value(j_list_parsed, G_OK)) {
                    json_array_foreach(json_object_get(j_list_parsed, "list"), index_c, j_element) {
                      json_object_set_new(j_element, "source", json_string(client_module->name));
                    }
                    cur_offset = 0;
                    if (cur_limit > json_array_size(json_object_get(j_list_parsed, "list"))) {
                      cur_limit -= json_array_size(json_object_get(j_list_parsed, "list"));
                    } else {
                      cur_limit = 0;
                    }
                    json_array_extend(json_object_get(j_return, "client"), json_object_get(j_list_parsed, "list"));
                  } else {
                    y_log_message(Y_LOG_LEVEL_ERROR, "get_client_list - Error client_module_get_list for module %s", json_string_value(json_object_get(j_module, "name")));
                  }
                  json_decref(j_list_parsed);
                } else {
                  cur_offset -= count_total;
                }
              } else if (client_module == NULL) {
                y_log_message(Y_LOG_LEVEL_ERROR, "get_client_list - Error, client_module_instance %s is NULL", json_string_value(json_object_get(j_module, "name")));
              }
            }
          } else if (res != G_ERROR_NOT_FOUND) {
            y_log_message(Y_LOG_LEVEL_ERROR, "get_client_list - Error is_client_backend_api_run_enabled (2)");
          }
        }
      } else {
        y_log_message(Y_LOG_LEVEL_ERROR, "get_client_list - Error allocating resources for j_return");
        j_return = json_pack("{si}", "result", G_ERROR);
      }
    } else {
      y_log_message(Y_LOG_LEVEL_ERROR, "get_client_list - Error get_client_module_list");
      j_return = json_pack("{si}", "result", G_ERROR);
    }
    json_decref(j_module_list);
  }
  return j_return;
}

json_t * is_client_valid(struct config_elements * config, const char * client_id, json_t * j_client, int add, const char * source) {
  int found = 0, res;
  json_t * j_return = NULL, * j_error_list, * j_module_list, * j_module;
  struct _client_module_instance * client_module;
  size_t index;
  
  if (source != NULL) {
    if ((res = is_client_backend_api_run_enabled(config, source)) == G_OK) {
      client_module = get_client_module_instance(config, source);
      if (client_module != NULL && client_module->enabled && !client_module->readonly) {
        j_error_list = client_module->module->client_module_is_valid(config->config_m, client_id, j_client, add?GLEWLWYD_IS_VALID_MODE_ADD:GLEWLWYD_IS_VALID_MODE_UPDATE, client_module->cls);
        if (check_result_value(j_error_list, G_ERROR_PARAM) || check_result_value(j_error_list, G_OK)) {
          j_return = json_incref(j_error_list);
        } else {
          y_log_message(Y_LOG_LEVEL_ERROR, "is_client_valid - Error, client_module_is_valid for module %s", client_module->name);
          j_return = json_pack("{si}", "result", G_ERROR);
        }
        json_decref(j_error_list);
      } else if (client_module != NULL && client_module->readonly) {
        j_return = json_pack("{sis[s]}", "result", G_ERROR_PARAM, "error", "module is read-only");
      } else if (client_module != NULL && !client_module->enabled) {
        j_return = json_pack("{sis[s]}", "result", G_ERROR_PARAM, "error", "module is unavailable");
      } else {
        y_log_message(Y_LOG_LEVEL_ERROR, "is_client_valid - Error get_client_module_instance");
        j_return = json_pack("{si}", "result", G_ERROR_NOT_FOUND);
      }
    } else if (res != G_ERROR_NOT_FOUND) {
      y_log_message(Y_LOG_LEVEL_ERROR, "is_client_valid - Error is_client_backend_api_run_enabled (1)");
      j_return = json_pack("{si}", "result", G_ERROR);
    } else {
      j_return = json_pack("{si}", "result", G_ERROR_NOT_FOUND);
    }
  } else {
    j_module_list = get_client_module_list(config);
    if (check_result_value(j_module_list, G_OK)) {
      json_array_foreach(json_object_get(j_module_list, "module"), index, j_module) {
        if ((res = is_client_backend_api_run_enabled(config, json_string_value(json_object_get(j_module, "name")))) == G_OK) {
          if (!found) {
            client_module = get_client_module_instance(config, json_string_value(json_object_get(j_module, "name")));
            if (client_module != NULL && client_module->enabled && !client_module->readonly) {
              found = 1;
              j_error_list = client_module->module->client_module_is_valid(config->config_m, client_id, j_client, add?GLEWLWYD_IS_VALID_MODE_ADD:GLEWLWYD_IS_VALID_MODE_UPDATE, client_module->cls);
              if (check_result_value(j_error_list, G_ERROR_PARAM) || check_result_value(j_error_list, G_OK)) {
                j_return = json_incref(j_error_list);
              } else {
                y_log_message(Y_LOG_LEVEL_ERROR, "is_client_valid - Error, client_module_is_valid for module %s", client_module->name);
                j_return = json_pack("{si}", "result", G_ERROR);
              }
              json_decref(j_error_list);
            } else if (client_module == NULL) {
              y_log_message(Y_LOG_LEVEL_ERROR, "is_client_valid - Error, client_module_instance %s is NULL", json_string_value(json_object_get(j_module, "name")));
            }
          }
        } else if (res != G_ERROR_NOT_FOUND) {
          y_log_message(Y_LOG_LEVEL_ERROR, "is_client_valid - Error is_client_backend_api_run_enabled (2)");
        }
      }
    } else {
      y_log_message(Y_LOG_LEVEL_ERROR, "is_client_valid - Error get_client_module_list");
      j_return = json_pack("{si}", "result", G_ERROR);
    }
    json_decref(j_module_list);
    if (j_return == NULL) {
      j_return = json_pack("{si}", "result", G_ERROR_PARAM);
    }
  }
  return j_return;
}

int add_client(struct config_elements * config, json_t * j_client, const char * source) {
  int found = 0, result, ret, res;
  json_t * j_module_list, * j_module;
  struct _client_module_instance * client_module;
  size_t index;
  
  if (source != NULL) {
    if ((res = is_client_backend_api_run_enabled(config, source)) == G_OK) {
      client_module = get_client_module_instance(config, source);
      if (client_module != NULL && client_module->enabled && !client_module->readonly) {
        result = client_module->module->client_module_add(config->config_m, j_client, client_module->cls);
        if (result == G_OK) {
          ret = G_OK;
        } else {
          y_log_message(Y_LOG_LEVEL_ERROR, "add_client - Error client_module_add");
          ret = result;
        }
      } else if (client_module != NULL && (client_module->readonly || !client_module->enabled)) {
        y_log_message(Y_LOG_LEVEL_ERROR, "add_client - Error module %s", source);
        ret = G_ERROR_PARAM;
      } else {
        y_log_message(Y_LOG_LEVEL_ERROR, "add_client - Error get_client_module_instance");
        ret = G_ERROR;
      }
    } else if (res != G_ERROR_NOT_FOUND) {
      y_log_message(Y_LOG_LEVEL_ERROR, "add_client - Error is_client_backend_api_run_enabled (1)");
      ret = G_ERROR;
    } else {
      ret = G_ERROR_PARAM;
    }
  } else {
    j_module_list = get_client_module_list(config);
    if (check_result_value(j_module_list, G_OK)) {
      json_array_foreach(json_object_get(j_module_list, "module"), index, j_module) {
        if ((res = is_client_backend_api_run_enabled(config, json_string_value(json_object_get(j_module, "name")))) == G_OK) {
          if (!found) {
            client_module = get_client_module_instance(config, json_string_value(json_object_get(j_module, "name")));
            if (client_module != NULL && client_module->enabled && !client_module->readonly) {
              found = 1;
              result = client_module->module->client_module_add(config->config_m, j_client, client_module->cls);
              if (result == G_OK) {
                ret = G_OK;
              } else {
                y_log_message(Y_LOG_LEVEL_ERROR, "add_client - Error client_module_add");
                ret = result;
              }
            } else if (client_module == NULL) {
              y_log_message(Y_LOG_LEVEL_ERROR, "add_client - Error, client_module_instance %s is NULL", json_string_value(json_object_get(j_module, "name")));
            }
          }
        } else if (res != G_ERROR_NOT_FOUND) {
          y_log_message(Y_LOG_LEVEL_ERROR, "add_client - Error is_client_backend_api_run_enabled (2)");
        }
      }
    } else {
      y_log_message(Y_LOG_LEVEL_ERROR, "add_client - Error get_client_module_list");
      ret = G_ERROR;
    }
    json_decref(j_module_list);
    if (!found) {
      y_log_message(Y_LOG_LEVEL_ERROR, "add_client - Error no module in write mode available");
      ret = G_ERROR;
    }
  }
  return ret;
}

int set_client(struct config_elements * config, const char * client_id, json_t * j_client, const char * source) {
  int found = 0, ret, result, res;
  struct _client_module_instance * client_module;
  json_t * j_cur_client, * j_module_list, * j_module;
  size_t index;
  
  if (source != NULL) {
    if ((res = is_client_backend_api_run_enabled(config, source)) == G_OK) {
      client_module = get_client_module_instance(config, source);
      if (client_module != NULL && client_module->enabled && !client_module->readonly) {
        j_cur_client = client_module->module->client_module_get(config->config_m, client_id, client_module->cls);
        if (check_result_value(j_cur_client, G_OK)) {
          ret = client_module->module->client_module_update(config->config_m, client_id, j_client, client_module->cls);
          if (ret != G_OK) {
            y_log_message(Y_LOG_LEVEL_ERROR, "set_client - Error client_module_update");
          }
        } else if (check_result_value(j_cur_client, G_ERROR_NOT_FOUND)) {
          ret = G_ERROR_NOT_FOUND;
        } else {
          y_log_message(Y_LOG_LEVEL_ERROR, "set_client - Error client_module_get");
          ret = G_ERROR;
        }
        json_decref(j_cur_client);
      } else if (client_module != NULL && (client_module->readonly || !client_module->enabled)) {
        ret = G_ERROR_PARAM;
      } else {
        y_log_message(Y_LOG_LEVEL_ERROR, "set_client - Error get_client_module_instance");
        ret = G_ERROR;
      }
    } else if (res != G_ERROR_NOT_FOUND) {
      y_log_message(Y_LOG_LEVEL_ERROR, "set_client - Error is_client_backend_api_run_enabled (1)");
      ret = G_ERROR;
    } else {
      ret = G_ERROR_NOT_FOUND;
    }
  } else {
    j_module_list = get_client_module_list(config);
    if (check_result_value(j_module_list, G_OK)) {
      json_array_foreach(json_object_get(j_module_list, "module"), index, j_module) {
        if ((res = is_client_backend_api_run_enabled(config, json_string_value(json_object_get(j_module, "name")))) == G_OK) {
          if (!found) {
            client_module = get_client_module_instance(config, json_string_value(json_object_get(j_module, "name")));
            if (client_module != NULL && client_module->enabled && !client_module->readonly) {
              found = 1;
              result = client_module->module->client_module_update(config->config_m, client_id, j_client, client_module->cls);
              if (result == G_OK) {
                ret = G_OK;
              } else {
                y_log_message(Y_LOG_LEVEL_ERROR, "set_client - Error client_module_update");
                ret = result;
              }
            } else if (client_module == NULL) {
              y_log_message(Y_LOG_LEVEL_ERROR, "set_client - Error, client_module_instance %s is NULL", json_string_value(json_object_get(j_module, "name")));
            }
          }
        } else if (res != G_ERROR_NOT_FOUND) {
          y_log_message(Y_LOG_LEVEL_ERROR, "set_client - Error is_client_backend_api_run_enabled (2)");
        }
      }
    } else {
      y_log_message(Y_LOG_LEVEL_ERROR, "set_client - Error get_client_module_list");
      ret = G_ERROR;
    }
    json_decref(j_module_list);
    if (!found) {
      y_log_message(Y_LOG_LEVEL_ERROR, "set_client - Error no module in write mode available");
      ret = G_ERROR;
    }
  }
  return ret;
}

int delete_client(struct config_elements * config, const char * client_id, const char * source) {
  int found = 0, ret, result, res;
  struct _client_module_instance * client_module;
  json_t * j_client, * j_module_list, * j_module;
  size_t index;
  
  if (source != NULL) {
    if ((res = is_client_backend_api_run_enabled(config, source)) == G_OK) {
      client_module = get_client_module_instance(config, source);
      if (client_module != NULL && client_module->enabled && !client_module->readonly) {
        j_client = client_module->module->client_module_get(config->config_m, client_id, client_module->cls);
        if (check_result_value(j_client, G_OK)) {
          result = client_module->module->client_module_delete(config->config_m, client_id, client_module->cls);
          if (result == G_OK) {
            ret = G_OK;
          } else {
            y_log_message(Y_LOG_LEVEL_ERROR, "delete_client - Error client_module_delete");
            ret = result;
          }
        } else if (check_result_value(j_client, G_ERROR_NOT_FOUND)) {
          ret = G_ERROR_NOT_FOUND;
        } else {
          y_log_message(Y_LOG_LEVEL_ERROR, "delete_client - Error client_module_get");
          ret = G_ERROR;
        }
        json_decref(j_client);
      } else if (client_module != NULL && (client_module->readonly || !client_module->enabled)) {
        ret = G_ERROR_PARAM;
      } else {
        y_log_message(Y_LOG_LEVEL_ERROR, "delete_client - Error get_client_module_instance");
        ret = G_ERROR;
      }
    } else if (res != G_ERROR_NOT_FOUND) {
      y_log_message(Y_LOG_LEVEL_ERROR, "delete_client - Error is_client_backend_api_run_enabled (1)");
      ret = G_ERROR;
    } else {
      ret = G_ERROR_NOT_FOUND;
    }
  } else {
    j_module_list = get_client_module_list(config);
    if (check_result_value(j_module_list, G_OK)) {
      json_array_foreach(json_object_get(j_module_list, "module"), index, j_module) {
        if ((res = is_client_backend_api_run_enabled(config, json_string_value(json_object_get(j_module, "name")))) == G_OK) {
          if (!found) {
            client_module = get_client_module_instance(config, json_string_value(json_object_get(j_module, "name")));
            if (client_module != NULL && client_module->enabled && !client_module->readonly) {
              found = 1;
              result = client_module->module->client_module_delete(config->config_m, client_id, client_module->cls);
              if (result == G_OK) {
                ret = G_OK;
              } else {
                y_log_message(Y_LOG_LEVEL_ERROR, "delete_client - Error client_module_delete");
                ret = result;
              }
            } else if (client_module == NULL) {
              y_log_message(Y_LOG_LEVEL_ERROR, "delete_client - Error, client_module_instance %s is NULL", json_string_value(json_object_get(j_module, "name")));
            }
          }
        } else if (res != G_ERROR_NOT_FOUND) {
          y_log_message(Y_LOG_LEVEL_ERROR, "delete_client - Error is_client_backend_api_run_enabled (2)");
        }
      }
    } else {
      y_log_message(Y_LOG_LEVEL_ERROR, "delete_client - Error get_client_module_list");
      ret = G_ERROR;
    }
    json_decref(j_module_list);
    if (!found) {
      y_log_message(Y_LOG_LEVEL_ERROR, "delete_client - Error no module in write mode available");
      ret = G_ERROR;
    }
  }
  return ret;
}
