#include "clog.h" #include "cgi.h" #include "input.h" #include "wrenchboard_api.h" #include "reco_engine.h" //error in file name #include "email.h" #include "safestring.h" #include #include "pgsql.h" #include "pgsql_wrapper.h" #include #include "account.h" #include "cards.h" #include "twilo.h" #include "mobile.h" #include "jobs_manager.h" #include "family_acc.h" #include "common_tool.h" #include "account.h" long WrenchFamilyList(CVars in, CVars &out); long WrenchFamilyWallet(CVars in, CVars &out); long WrenchFamilyAdd(CVars in, CVars &out); long WrenchFamilyUpdate(CVars in, CVars &out); long WrenchFamilyManage(CVars in, CVars &out); long WrenchSampleTasks(CVars in, CVars &out); long WrenchSuggestTasks(CVars in, CVars &out); long WrenchSuggestList(CVars in, CVars &out); long WrenchSuggestWaitingList(CVars in, CVars &out); long WrenchSuggestTaskStatus(CVars in, CVars &out); long family_calls(CVars in, CVars &out){ logfmt(logINFO, "family_calls()"); out["result"] = "YES I GET TO BACK END"; long action = REQ_LONG(in, "action", 0, -1); CVars x; long ret = 0; const char * loc = getenv("REMOTE_ADDR"); const PGresult *res; logfmt(logINFO, "action = %ld", action); switch (action) { case WRENCHBOARD_FAMILY_LIST: return WrenchFamilyList(in, out); break; case WRENCHBOARD_FAMILY_WALLET: return WrenchFamilyWallet(in, out); break; case WRENCHBOARD_FAMILY_SAMPLETASKS: return WrenchSampleTasks(in, out); break; case WRENCHBOARD_FAMILY_SGGESTSTATUS: logfmt(logINFO, "ENTER CALL long WRENCHBOARD_FAMILY_SGGESTTASKS"); return WrenchSuggestTaskStatus(in, out); break; case WRENCHBOARD_FAMILY_ADD: return WrenchFamilyAdd(in, out); break; case WRENCHBOARD_FAMILY_UPDATE: return WrenchFamilyUpdate(in, out); break; case WRENCHBOARD_FAMILY_MANAGE: return WrenchFamilyManage(in, out); break; case WRENCHBOARD_FAMILY_SGGESTTASKS: logfmt(logINFO, "ENTER CALL long WRENCHBOARD_FAMILY_SGGESTTASKS"); return WrenchSuggestTasks(in, out); break; case WRENCHBOARD_FAMILY_SGGESTLIST: logfmt(logINFO, "ENTER CALL long WRENCHBOARD_FAMILY_SGGESTLIST"); return WrenchSuggestList(in, out); break; //long WrenchSuggestWaitingList(CVars in, CVars &out) case WRENCHBOARD_FAMILY_SGGESTWAITING: logfmt(logINFO, "ENTER CALL long WRENCHBOARD_FAMILY_SGGESTWAITING"); return WrenchSuggestWaitingList(in, out); // this now the parent break; } return 0; } long WrenchSuggestWaitingList(CVars in, CVars &out){ // this is the parent now logfmt(logINFO, "ENTER CALL long WrenchSuggestWaitingList"); char vname[30]; long ret = PHP_API_BAD_PARAM; const PGresult *res; try{ long member_id = REQ_LONG(in, "member_id", 1, -1); long offset = REQ_LONG(in, "offset", 1, -1); long limit = REQ_LONG(in, "limit", 1, -1); out["total_record"] = "0"; // res = pgsql_query("SELECT id FROM family_task_suggestion WHERE status=1 "); // out["total_record"] = pgsql_num_rows(res); res = pgsql_query("SELECT sg.*,mf.firstname,to_char(sg.created, 'Day Mon dd, yyyy HH:MI AM') AS formarted_added " " FROM members_family_suggesttask sg " " LEFT JOIN members_family mf ON mf.uid::text = sg.family_uid " " WHERE sg.family_uid::text IN (SELECT uid::text FROM members_family " " WHERE member_id = %lu ) " " AND sg.status IN ( 1,2,3,4,5) " " ORDER BY sg.created DESC LIMIT %lu OFFSET %lu", member_id, limit, offset); if (res != NULL && pgsql_num_rows(res) > 0) { out["total_record"] = pgsql_num_rows(res); for (int i = 0, n = pgsql_num_rows(res); i < n; i++) { mapf = pgsql_fetch_assoc(res, i); if (f.empty()) continue; CVars rec; map_to_cvars(f, rec); snprintf(vname, sizeof (vname), "uid_%05d", i); out[vname] = rec["uid"]; snprintf(vname, sizeof (vname), "family_uid_%05d", i); out[vname] = rec["family_uid"]; snprintf(vname, sizeof (vname), "title_%05d", i); out[vname] = rec["title"]; snprintf(vname, sizeof (vname), "description_%05d", i); out[vname] = rec["description"]; snprintf(vname, sizeof (vname), "added_%05d", i); out[vname] = rec["formarted_added"]; snprintf(vname, sizeof (vname), "status_%05d", i); out[vname] = rec["status"]; snprintf(vname, sizeof (vname), "banner_%05d", i); out[vname] = rec["banner"]; snprintf(vname, sizeof (vname), "firstname_%05d", i); out[vname] = rec["firstname"]; } } ret = PHP_API_OK; out["status"] = "OK"; } catch (bad_parameter) { logfmt(logINFO, "ERROR CALL long WrenchSuggestWaitingList"); } logfmt(logINFO, "WrenchSuggestList()"); return ret; } long WrenchSuggestList(CVars in, CVars &out){ logfmt(logINFO, "ENTER CALL long WrenchSuggestList"); char vname[30]; long ret = PHP_API_BAD_PARAM; const PGresult *res; try{ long member_id = REQ_LONG(in, "member_id", 1, -1); long offset = REQ_LONG(in, "offset", 1, -1); long limit = REQ_LONG(in, "limit", 1, -1); out["total_record"] = "0"; // res = pgsql_query("SELECT id FROM family_task_suggestion WHERE status=1 "); // out["total_record"] = pgsql_num_rows(res); //ALTER TABLE members_family_suggesttask ADD remind timestamp; res = pgsql_query(" SELECT * FROM members_family_suggesttask WHERE member_id = %lu AND status IN ( 1,2,3,4,5) " " ORDER BY created DESC LIMIT %lu OFFSET %lu", member_id, limit, offset); if (res != NULL && pgsql_num_rows(res) > 0) { out["total_record"] = pgsql_num_rows(res); for (int i = 0, n = pgsql_num_rows(res); i < n; i++) { mapf = pgsql_fetch_assoc(res, i); if (f.empty()) continue; CVars rec; map_to_cvars(f, rec); snprintf(vname, sizeof (vname), "uid_%05d", i); out[vname] = rec["uid"]; snprintf(vname, sizeof (vname), "title_%05d", i); out[vname] = rec["title"]; snprintf(vname, sizeof (vname), "description_%05d", i); out[vname] = rec["description"]; snprintf(vname, sizeof (vname), "added_%05d", i); out[vname] = rec["created"]; snprintf(vname, sizeof (vname), "status_%05d", i); out[vname] = rec["status"]; snprintf(vname, sizeof (vname), "banner_%05d", i); out[vname] = rec["banner"]; snprintf(vname, sizeof (vname), "remind_%05d", i); out[vname] = rec["remind"]; } } ret = PHP_API_OK; out["status"] = "OK"; } catch (bad_parameter) { logfmt(logINFO, "ERROR CALL long WrenchSuggestList"); } logfmt(logINFO, "WrenchSuggestList()"); return ret; } long WrenchSuggestTaskStatus(CVars in, CVars &out){ long ret = PHP_API_BAD_PARAM; // const PGresult *res; try{ long member_id = REQ_LONG(in, "member_id", 1, -1); REQ_STRING(in, "uid", 3, 150, "(.*)"); REQ_STRING(in, "suggest_uid", 3, 150, "(.*)"); long suggest_action = REQ_LONG(in, "suggest_action", 1, -1); out["suggested_task_id"] ="0";// we will set if all okay const PGresult *res = pgsql_query("SELECT m.*,mf.uid AS family_uid FROM members m " " LEFT JOIN members_family mf ON mf.family_member_id = m.id " " WHERE m.id=%lu AND m.uid='%s'", member_id, in["uid"].c_str()); if (res != NULL && pgsql_num_rows(res) > 0) { mapf = pgsql_fetch_assoc(res, 0); CVars rec; map_to_cvars(f, rec); ret = PHP_API_OK; out["status"] = "ACCOUNT FOUND"; //out = rec; if (rec["family_uid"] != ""){ // we are sure you are a family now // NOW LET US FIND THIS TASK logfmt(logINFO, " CALL long WrenchSuggestTaskStatus- NOW LET US FIND THIS TASK"); const PGresult *res0 = pgsql_query("SELECT id AS suggest_id,* FROM members_family_suggesttask " " WHERE member_id = %lu AND uid='%s' AND status IN (1,2)", member_id, in["suggest_uid"].c_str()); if (res0 != NULL && pgsql_num_rows(res0) > 0) { mapf = pgsql_fetch_assoc(res0, 0); CVars rec2; map_to_cvars(f, rec2); if (suggest_action == 555 ){ pgsql_exec("UPDATE members_family_suggesttask SET status=0,updated=now() " " WHERE id=%lu AND uid='%s'", rec2["suggest_id"].Long(),in["suggest_uid"].c_str() ); out["status"] = "OK"; out["status_msg"] = "family_suggest_deleted"; ret = PHP_API_OK; } if (suggest_action == 222 ){ pgsql_exec("UPDATE members_family_suggesttask SET remind=now(),updated=now() " " WHERE id=%lu AND uid='%s'", rec2["suggest_id"].Long(), in["suggest_uid"].c_str() ); family_email(WRENCHBOARD_FAMILY_SGGESTTASKS, rec2, rec2); out["status"] = "OK"; out["status_msg"] = "family_suggest_reminder_sent"; ret = PHP_API_OK; } } } } } catch (bad_parameter) { logfmt(logINFO, "ERROR CALL long WrenchSuggestTaskStatus"); } logfmt(logINFO, "WrenchSuggestTaskStatus()"); return ret; } long WrenchSuggestTasks(CVars in, CVars &out){ long ret = PHP_API_BAD_PARAM; // const PGresult *res; try{ long member_id = REQ_LONG(in, "member_id", 1, -1); REQ_STRING(in, "uid", 3, 150, "(.*)"); REQ_STRING(in, "title", 3, 150, "(.*)"); REQ_STRING(in, "description", 3, 299, "(.*)"); REQ_STRING(in, "banner", 3, 25, "(.*)"); out["suggested_task_id"] ="0";// we will set if all okay const PGresult *res = pgsql_query("SELECT m.*,mf.uid AS family_uid FROM members m " " LEFT JOIN members_family mf ON mf.family_member_id = m.id " " WHERE m.id=%lu AND m.uid='%s'", member_id, in["uid"].c_str()); if (res != NULL && pgsql_num_rows(res) > 0) { mapf = pgsql_fetch_assoc(res, 0); CVars rec; map_to_cvars(f, rec); ret = PHP_API_OK; out["status"] = "ACCOUNT FOUND"; //out = rec; if (rec["family_uid"] != ""){ // we are sure you are a family now CVars xx; xx["member_id"] = member_id; xx["member_id"].set_valid(true); xx["title"] = in["title"]; xx["title"].set_valid(true); xx["description"] = in["description"]; xx["description"].set_valid(true); xx["family_uid"] = rec["family_uid"]; xx["family_uid"].set_valid(true); xx["banner"] = in["banner"]; xx["banner"].set_valid(true); out["suggested_task_id"] = insert_db_record(DBS_VALID, "members_family_suggesttask", "members_family_suggesttask_id_seq", xx); if(out["suggested_task_id"].Long() > 0 ){ load_db_record( out, "SELECT id AS suggest_id,* FROM members_family_suggesttask WHERE id = %lu ", out["suggested_task_id"].Long()); family_email(WRENCHBOARD_FAMILY_SGGESTTASKS, out, out); // } ret = PHP_API_OK; out["status"] = "OK"; } } } catch (bad_parameter) { logfmt(logINFO, "ERROR CALL long WrenchSuggestTasks"); } logfmt(logINFO, "WrenchSuggestTasks()"); return ret; } long WrenchSampleTasks(CVars in, CVars &out){ logfmt(logINFO, "ENTER CALL long WrenchSampleTasks"); char vname[30]; long ret = PHP_API_BAD_PARAM; const PGresult *res; try{ long member_id = REQ_LONG(in, "member_id", 1, -1); long offset = REQ_LONG(in, "offset", 1, -1); long limit = REQ_LONG(in, "limit", 1, -1); out["total_record"] = "0"; // res = pgsql_query("SELECT id FROM family_task_suggestion WHERE status=1 "); // out["total_record"] = pgsql_num_rows(res); res = pgsql_query(" SELECT * FROM family_task_suggestion WHERE status = 1 " " ORDER BY title DESC LIMIT %lu OFFSET %lu", limit, offset); if (res != NULL && pgsql_num_rows(res) > 0) { out["total_record"] = pgsql_num_rows(res); for (int i = 0, n = pgsql_num_rows(res); i < n; i++) { mapf = pgsql_fetch_assoc(res, i); if (f.empty()) continue; CVars rec; map_to_cvars(f, rec); snprintf(vname, sizeof (vname), "uid_%05d", i); out[vname] = rec["uid"]; snprintf(vname, sizeof (vname), "title_%05d", i); out[vname] = rec["title"]; snprintf(vname, sizeof (vname), "description_%05d", i); out[vname] = rec["description"]; snprintf(vname, sizeof (vname), "added_%05d", i); out[vname] = rec["added"]; snprintf(vname, sizeof (vname), "age_%05d", i); out[vname] = rec["age"]; snprintf(vname, sizeof (vname), "banner_%05d", i); out[vname] = rec["banner"]; } } ret = PHP_API_OK; out["status"] = "OK"; } catch (bad_parameter) { logfmt(logINFO, "ERROR CALL long WrenchSampleTasks"); } logfmt(logINFO, "WrenchSampleTasks()"); return ret; } long WrenchFamilyWallet(CVars in, CVars &out){ logfmt(logINFO, "ENTER CALL long WrenchFamilyWallet"); char vname[30]; long ret = PHP_API_BAD_PARAM; const PGresult *res0; try { long member_id = REQ_LONG(in, "member_id", 1, -1); REQ_STRING(in, "family_uid", 2, 50, "(.*)"); REQ_STRING(in, "uid", 2, 50, "(.*)"); REQ_STRING(in, "sessionid", 2, 149, "(.*)"); logfmt(logINFO, "WrenchFamilyWallet() Verify Session "); CVars rec0; if ( VerifySession(in, out) != PHP_API_OK ){ return 0; } res0 = pgsql_query("SELECT family_member_id FROM members_family WHERE member_id = %lu AND uid='%s' ", in["member_id"].Long(), in["family_uid"].c_str()); if (res0 != NULL && pgsql_num_rows(res0) > 0) { mapf = pgsql_fetch_assoc(res0, 0); map_to_cvars(f, rec0); } else{ return 0; } out["total_record"] = "0"; const PGresult *res; res = pgsql_query("SELECT w.amount,c.*,w.amount AS current_balance,c.country,w.transfer_limit,w.uid AS wallet_uid " "FROM members_wallet w LEFT JOIN currency c ON c.code=w.currency " "WHERE w.member_id = %lu ORDER BY c.lorder DESC", rec0["family_member_id"].Long()); if (res != NULL && pgsql_num_rows(res) > 0) { out["total_record"] = pgsql_num_rows(res); for (int i = 0, n = pgsql_num_rows(res); i < n; i++) { mapf = pgsql_fetch_assoc(res, i); if (f.empty()) continue; CVars rec; map_to_cvars(f, rec); snprintf(vname, sizeof (vname), "amount_%05d", i); out[vname] = rec["amount"]; snprintf(vname, sizeof (vname), "currency_%05d", i); out[vname] = rec["currency"]; // amount | id | code | description | symbol | action_type | lorder | current_balance snprintf(vname, sizeof (vname), "description_%05d", i); out[vname] = rec["description"]; snprintf(vname, sizeof (vname), "symbol_%05d", i); out[vname] = rec["symbol"]; snprintf(vname, sizeof (vname), "action_type_%05d", i); out[vname] = rec["action_type"]; snprintf(vname, sizeof (vname), "code_%05d", i); out[vname] = rec["code"]; snprintf(vname, sizeof (vname), "country_%05d", i); out[vname] = rec["country"]; snprintf(vname, sizeof (vname), "transfer_limit_%05d", i); out[vname] = rec["transfer_limit"]; snprintf(vname, sizeof (vname), "wallet_uid_%05d", i); out[vname] = rec["wallet_uid"]; } } ret = PHP_API_OK; out["status"] = "OK"; } catch (bad_parameter) { logfmt(logINFO, "ERROR CALL long WrenchFamilyWallet(CVars in, CVars &out)"); } logfmt(logINFO, "EXIT CALL long WrenchFamilyWallet"); return 0; } //,to_char(last_login, 'Day Mon dd, yyyy HH:MI AM') long WrenchFamilyList(CVars in, CVars &out){ logfmt(logINFO, "ENTER CALL long WrenchFamilyList"); char vname[30]; long ret = PHP_API_BAD_PARAM; const PGresult *res; try{ long member_id = REQ_LONG(in, "member_id", 1, -1); long offset = REQ_LONG(in, "offset", 1, -1); long limit = REQ_LONG(in, "limit", 1, -1); out["total_record"] = "0"; res = pgsql_query("SELECT id FROM members_family WHERE member_id = %lu AND status=1 ", in["member_id"].Long()); out["total_record"] = pgsql_num_rows(res); res = pgsql_query(" SELECT *,to_char(last_login, 'Day Mon dd, yyyy HH:MI AM') AS last_login_formatted FROM members_family WHERE member_id = %lu AND status=1 " " ORDER BY id DESC LIMIT %lu OFFSET %lu", in["member_id"].Long(), limit, offset); if (res != NULL && pgsql_num_rows(res) > 0) { out["total_record"] = pgsql_num_rows(res); for (int i = 0, n = pgsql_num_rows(res); i < n; i++) { mapf = pgsql_fetch_assoc(res, i); if (f.empty()) continue; CVars rec; map_to_cvars(f, rec); snprintf(vname, sizeof (vname), "uid_%05d", i); out[vname] = rec["uid"]; snprintf(vname, sizeof (vname), "firstname_%05d", i); out[vname] = rec["firstname"]; snprintf(vname, sizeof (vname), "lastname_%05d", i); out[vname] = rec["lastname"]; snprintf(vname, sizeof (vname), "added_%05d", i); out[vname] = rec["added"]; snprintf(vname, sizeof (vname), "age_%05d", i); out[vname] = rec["age"]; snprintf(vname, sizeof (vname), "last_login_%05d", i); out[vname] = rec["last_login_formatted"]; snprintf(vname, sizeof (vname), "task_count_%05d", i); out[vname] = rec["task_count"]; snprintf(vname, sizeof (vname), "year_%05d", i); out[vname] = rec["year"]; snprintf(vname, sizeof (vname), "month_%05d", i); out[vname] = rec["month"]; } } ret = PHP_API_OK; out["status"] = "OK"; } catch (bad_parameter) { logfmt(logINFO, "ERROR CALL long WrenchFamilyList"); } logfmt(logINFO, "WrenchFamilyList()"); return ret; } long WrenchFamilyAdd(CVars in, CVars &out){ logfmt(logINFO, "WrenchFamilyAdd()"); long family_id = 0; try { REQ_LONG(in, "member_id", 1, -1); //REQ_LONG(in, "age", 1, -1); REQ_LONG(in, "year", 1, -1); REQ_LONG(in, "month", 1, -1); REQ_STRING(in, "firstname", 2, 34, "(.*)"); REQ_STRING(in, "lastname", 2, 34, "(.*)"); CVars x; x["member_id"] = in["member_id"]; x["member_id"].set_valid(true); x["age"] = "0"; x["age"].set_valid(true); x["firstname"] = in["firstname"]; x["firstname"].set_valid(true); x["lastname"] = in["lastname"]; x["lastname"].set_valid(true); x["status"] = "1"; x["status"].set_valid(true); x["year"] = in["year"]; x["year"].set_valid(true); x["month"] = in["month"]; x["month"].set_valid(true); family_id = insert_db_record(DBS_VALID, "members_family", "members_family_id_seq", x); if (family_id > 0) { load_db_record(out, "SELECT * FROM members_family WHERE id =%lu",family_id); // send notice here } out["status"] = "OK"; } catch (bad_parameter) { logfmt(logINFO, "ERROR CALL long WrenchFamilyAdd(CVars in, CVars &out)"); } logfmt(logINFO, "WrenchFamilyAdd()"); return family_id; } long WrenchFamilyUpdate(CVars in, CVars &out){ long ret = PHP_API_BAD_PARAM; logfmt(logINFO, "WrenchFamilyUpdate()"); long family_id = 0; try { long member_id = REQ_LONG(in, "member_id", 1, -1); REQ_STRING(in, "firstname", 2, 34, "(.*)"); REQ_STRING(in, "lastname", 2, 34, "(.*)"); REQ_STRING(in, "family_uid", 2, 50, "(.*)"); REQ_LONG(in, "year", 1, -1); REQ_LONG(in, "month", 1, -1); CVars x; x["firstname"] = in["firstname"]; x["firstname"].set_valid(true); x["lastname"] = in["lastname"]; x["lastname"].set_valid(true); x["year"] = in["year"]; x["year"].set_valid(true); x["month"] = in["month"]; x["month"].set_valid(true); const PGresult *res = pgsql_query(" SELECT id AS family_id FROM members_family " " WHERE member_id=%lu AND uid='%s' ", member_id,in["family_uid"].c_str()); if (res != NULL && pgsql_num_rows(res) > 0) { mapf = pgsql_fetch_assoc(res, 0); CVars rec; map_to_cvars(f, rec); update_db_record(DBS_VALID, "members_family", x, rec["family_id"].Long()); ret = PHP_API_OK; } out["status"] = "OK"; } catch (bad_parameter) { logfmt(logINFO, "ERROR CALL long WrenchFamilyUpdate(CVars in, CVars &out)"); } logfmt(logINFO, "WrenchFamilyUpdate()"); return ret; } long WrenchFamilyInitializeAccount(CVars in, CVars &out); long WrenchFamilyManage(CVars in, CVars &out){ /* wrenchboard=> select * from members_family; id | member_id | firstname | lastname | age | active | status | added | updated ----+-----------+-----------+----------+-----+--------+--------+-------+--------- (0 rows) */ long ret = PHP_API_BAD_PARAM; logfmt(logINFO, "WrenchFamilyManage()"); long family_id = 0; try { long member_id = REQ_LONG(in, "member_id", 1, -1); REQ_STRING(in, "uid", 2, 45, "(.*)"); REQ_STRING(in, "family_uid", 2, 45, "(.*)"); const PGresult *res = pgsql_query(" SELECT id AS family_id,* FROM members_family " " WHERE member_id=%lu AND uid='%s' ", member_id,in["family_uid"].c_str()); if (res != NULL && pgsql_num_rows(res) > 0) { mapf = pgsql_fetch_assoc(res, 0); CVars rec; map_to_cvars(f, rec); if( rec["username"]=="" || rec["pin"]==""){ logfmt(logINFO, "WrenchFamilyManage()- NEED TI INITIALIZE USERNAME PIN"); WrenchFamilyInitializeAccount(rec,out); } out = rec; ret = PHP_API_OK; } out["status"] = "OK"; } catch (bad_parameter) { logfmt(logINFO, "ERROR CALL long WrenchFamilyUpdate(CVars in, CVars &out)"); } logfmt(logINFO, "/WrenchFamilyManage()"); return ret; } long WrenchFamilyInitializeAccount(CVars in, CVars &out){ const PGresult *res; char username[7] = ""; logfmt(logINFO, "WrenchFamilyInitializeAccount()"); try { SetFamilyUsername(in["family_id"].Long(), username, 6); } catch (bad_parameter) { logfmt(logINFO, "ERROR CALL void SetFamilyUsername(CVars in, CVars &out)"); } /* int r1; //srand(time(NULL)); r1 = 1000+(rand()%9000); pgsql_exec("UPDATE members_family SET pin='%s' WHERE id=%lu", r1, in["family_id"].Long() ); */ pgsql_exec("UPDATE members_family SET pin='1234' WHERE id=%lu", in["family_id"].Long() ); load_db_record(out, "SELECT * FROM members_family WHERE id = %lu", in["family_id"].Long()); return 0; } /* #define WRENCHBOARD_FAMILY_LIST 22010 #define WRENCHBOARD_FAMILY_ADD 22015 #define WRENCHBOARD_FAMILY_UPDATE 22020 #define WRENCHBOARD_FAMILY_MANAGE 22025 */