#include "lbs_db.h"
-static char *get_user(edg_wll_Context ctx, int create);
-static int update_notif(edg_wll_Context, const edg_wll_NotifId,
- const char *, const char *, const char *);
+static char *get_user(edg_wll_Context ctx, int create);
+static int check_notif_request(edg_wll_Context, const edg_wll_NotifId, char **);
+static int split_cond_list(edg_wll_Context, edg_wll_QueryRec const * const *,
+ edg_wll_QueryRec ***, char ***);
+static int update_notif(edg_wll_Context, const edg_wll_NotifId,
+ const char *, const char *, const char *);
+
int edg_wll_NotifNewServer(
edg_wll_Context ctx,
const edg_wll_NotifId nid,
time_t *valid)
{
- int i, j,
- ct,
- new_rows;
+ int i;
char *q = NULL,
*nid_s = NULL,
*time_s = NULL,
goto cleanup;
/* Format conditions
- * - first of all separate all jobids
- * - then format new condition list without jobids and encode it into an XML string
+ * - separate all jobids
+ * - format new condition list without jobids
*/
- if ( !conditions || !conditions[0] )
- {
- edg_wll_SetError(ctx, EINVAL, "Empty condition list");
+ if ( split_cond_list(ctx, conditions, &nconds, &jobs) )
goto cleanup;
- }
- for ( new_rows = ct = i = 0; conditions[i]; i++ )
- {
- if ( conditions[i][0].attr && conditions[i][0].attr != EDG_WLL_QUERY_ATTR_JOBID )
- new_rows++;
- for ( j = 0; conditions[i][j].attr; j++ )
- if ( conditions[i][j].attr == EDG_WLL_QUERY_ATTR_JOBID )
- ct++;
- }
- if ( !ct )
- {
- edg_wll_SetError(ctx, EINVAL, "Notification has to bind to at least one jobID");
- goto cleanup;
- }
- if ( !(jobs = calloc(ct+1, sizeof(char *)))
- || !(nconds = calloc(new_rows+1, sizeof(edg_wll_QueryRec *))) )
- {
- edg_wll_SetError(ctx, errno, NULL);
- goto cleanup;
- }
- for ( ct = i = 0; conditions[i]; i++ )
- for ( j = 0; conditions[i][j].attr; j++ )
- if ( conditions[i][j].attr == EDG_WLL_QUERY_ATTR_JOBID )
- if ( !(jobs[ct++] = edg_wlc_JobIdGetUnique(conditions[i][j].value.j)) )
- {
- edg_wll_SetError(ctx, errno, NULL);
- goto cleanup;
- }
- for ( new_rows = i = 0; conditions[i]; i++ )
- if ( conditions[i][0].attr && conditions[i][0].attr != EDG_WLL_QUERY_ATTR_JOBID )
- /* !!! DO NOT DEALLOCATE this arrays (it is not neccessary to allocate new
- * mem - it's used only once and only for xml parsing
- */
- nconds[new_rows++] = (edg_wll_QueryRec *) (conditions[i]);
+
+ /*
+ * encode new cond. list into a XML string
+ */
if ( edg_wll_JobQueryRecToXML(ctx, (edg_wll_QueryRec const * const *) nconds, &xml_conds) )
{
/* XXX: edg_wll_JobQueryRecToXML() do not set errors in context!
const char *address_override,
time_t *valid)
{
- char *time_s = NULL;
+ char *time_s = NULL,
+ *addr_s = NULL;
if ( !address_override )
goto cleanup;
}
+ if ( check_notif_request(ctx, nid, NULL) )
+ goto cleanup;
+
/* Format time of validity
*/
*valid = time(NULL);
}
time_s[strlen(time_s)-1] = 0;
- update_notif(ctx, nid, NULL, address_override, (const char *)(time_s+1));
+ /* Format the address
+ */
+ if ( address_override )
+ {
+ char *aux;
+
+ if ( !(aux = strchr(address_override, ':')) )
+ {
+ edg_wll_SetError(ctx, EINVAL, "Addres overrirde not in format host:port");
+ goto cleanup;
+ }
+ if ( !strncmp(address_override, "0.0.0.0", aux-address_override) )
+ trio_asprintf(&addr_s, "%s:%s", ctx->connPool[ctx->connToUse].peerName, aux+1);
+ }
+
+
+ update_notif(ctx, nid, NULL, addr_s? addr_s: address_override, (const char *)(time_s+1));
cleanup:
if ( time_s ) free(time_s);
+ if ( addr_s ) free(addr_s);
return edg_wll_Error(ctx, NULL, NULL);
}
+
int edg_wll_NotifChangeServer(
edg_wll_Context ctx,
- const edg_wll_NotifId id,
+ const edg_wll_NotifId nid,
edg_wll_QueryRec const * const *conditions,
edg_wll_NotifChangeOp op)
{
- return edg_wll_SetError(ctx, EINVAL, "Not yet implemented");
+ int i;
+ char *q = NULL,
+ *nid_s = NULL,
+ *xml_conds = NULL,
+ **jobs = NULL;
+ edg_wll_QueryRec **nconds = NULL;
+
+
+ /* Format notification ID
+ */
+ if ( !(nid_s = edg_wll_NotifIdGetUnique(nid)) )
+ goto cleanup;
+
+ if ( check_notif_request(ctx, nid, NULL) )
+ goto cleanup;
+
+ switch ( op )
+ {
+ case EDG_WLL_NOTIF_REPLACE:
+ /* Format conditions
+ * - separate all jobids
+ * - format new condition list without jobids
+ */
+ if ( split_cond_list(ctx, conditions, &nconds, &jobs) )
+ goto cleanup;
+
+ /*
+ * encode new cond. list into a XML string
+ */
+ if ( edg_wll_JobQueryRecToXML(ctx, (edg_wll_QueryRec const * const *) nconds, &xml_conds) )
+ {
+ /* XXX: edg_wll_JobQueryRecToXML() do not set errors in context!
+ * can't get propper error number :(
+ */
+ edg_wll_SetError(ctx, errno, "Can't encode data into xml");
+ goto cleanup;
+ }
+
+ /* Format DB insert statement
+ */
+ if ( update_notif(ctx, nid, xml_conds, NULL, NULL) )
+ goto cleanup;
+
+ if ( jobs )
+ {
+ /* Format DB insert statement
+ */
+ trio_asprintf(&q, "delete from notif_jobs where notifid='%|Ss'", nid_s);
+ if ( edg_wll_ExecStmt(ctx, q, NULL) < 0 )
+ goto cleanup;
+
+ for ( i = 0; jobs[i]; i++ )
+ {
+ free(q);
+ trio_asprintf(&q,
+ "insert into notif_jobs(notifid,jobid) values ('%|Ss','%|Ss')",
+ nid_s, jobs[i]);
+ if ( edg_wll_ExecStmt(ctx, q, NULL) < 0 )
+ {
+ /* XXX: Remove uncoplete registration?
+ * Which error has to be returned?
+ */
+ free(q);
+ trio_asprintf(&q, "delete from notif_jobs where notifid='%|Ss'", nid_s);
+ edg_wll_ExecStmt(ctx, q, NULL);
+ free(q);
+ trio_asprintf(&q,"delete from notif_registrations where notifid='%|Ss'", nid_s);
+ edg_wll_ExecStmt(ctx, q, NULL);
+ goto cleanup;
+ }
+ }
+ }
+ break;
+
+ case EDG_WLL_NOTIF_ADD:
+ break;
+ case EDG_WLL_NOTIF_REMOVE:
+ break;
+ default:
+ break;
+ }
+
+cleanup:
+ if ( q ) free(q);
+ if ( xml_conds ) free(xml_conds);
+ if ( nid_s ) free(nid_s);
+ if ( jobs )
+ {
+ for ( i = 0; jobs[i]; i++ )
+ free(jobs[i]);
+ free(jobs);
+ }
+ if ( nconds ) free(nconds);
+
+ return edg_wll_Error(ctx, NULL, NULL);
}
int edg_wll_NotifRefreshServer(
char *time_s = NULL;
+ if ( check_notif_request(ctx, nid, NULL) )
+ goto cleanup;
+
/* Format time of validity
*/
*valid = time(NULL);
edg_wll_Context ctx,
edg_wll_NotifId *nid)
{
- char *owner = NULL,
- *nid_s = NULL,
+ char *nid_s = NULL,
*stmt;
int ret;
- if ( !(owner = get_user(ctx, 0)) )
- {
- if ( !edg_wll_Error(ctx, NULL, NULL) )
- edg_wll_SetError(ctx, EPERM, "Unknown user");
-
- return edg_wll_Error(ctx, NULL, NULL);
- }
+ if ( check_notif_request(ctx, nid, NULL) )
+ goto cleanup;
if ( !(nid_s = edg_wll_NotifIdGetUnique(nid)) )
goto cleanup;
- /* Only the owner could remove the notification registration
- */
- trio_asprintf(&stmt,
- "delete from notif_registrations where notifid='%|Ss' and userid='%|Ss'",
- nid_s, owner);
+ trio_asprintf(&stmt, "delete from notif_registrations where notifid='%|Ss'", nid_s);
if ( (ret = edg_wll_ExecStmt(ctx, stmt, NULL)) < 0 )
goto cleanup;
free(stmt);
- if ( ret == 0 )
- {
- trio_asprintf(&stmt,
- "select notifid from notif_registrations where notifid='%|Ss'", nid_s);
- ret = edg_wll_ExecStmt(ctx, stmt, NULL);
- if ( ret == 0 )
- edg_wll_SetError(ctx, ENOENT, "Unknown notification ID");
- else if ( ret > 0 )
- edg_wll_SetError(ctx, EPERM, NULL);
-
- goto cleanup;
- }
trio_asprintf(&stmt, "delete from notif_jobs where notifid='%|Ss'", nid_s);
edg_wll_ExecStmt(ctx, stmt, NULL);
cleanup:
- if ( owner ) free(owner);
if ( nid_s ) free(nid_s);
if ( stmt ) free(stmt);
return edg_wll_Error(ctx, NULL, NULL);
}
+
static char *get_user(edg_wll_Context ctx, int create)
{
edg_wll_Stmt stmt = NULL;
if ( !ctx->peerName )
{
- edg_wll_SetError(ctx, EPERM, "Annonymous notifications not allowed");
+ edg_wll_SetError(ctx, EPERM, "Annonymous access not allowed");
goto cleanup;
}
trio_asprintf(&q, "select userid from users where cert_subj='%|Ss'", ctx->peerName);
return userid;
}
-static int update_notif(
- edg_wll_Context ctx,
- const edg_wll_NotifId nid,
- const char *conds,
- const char *dest,
- const char *valid)
+
+static int check_notif_request(
+ edg_wll_Context ctx,
+ const edg_wll_NotifId nid,
+ char **owner)
{
- char *owner = NULL,
- *nid_s = NULL,
- *stmt, *aux;
+ char *nid_s = NULL,
+ *stmt, *user;
int ret;
- if ( !(owner = get_user(ctx, 0)) )
+ if ( !(user = get_user(ctx, 0)) )
{
if ( !edg_wll_Error(ctx, NULL, NULL) )
edg_wll_SetError(ctx, EPERM, "Unknown user");
if ( !(nid_s = edg_wll_NotifIdGetUnique(nid)) )
goto cleanup;
+ trio_asprintf(&stmt,
+ "select notifid from notif_registrations "
+ "where notifid='%|Ss' and userid='%|Ss'",
+ nid_s, user);
+
+ if ( (ret = edg_wll_ExecStmt(ctx, stmt, NULL)) < 0 )
+ goto cleanup;
+ if ( ret == 0 )
+ {
+ free(stmt);
+ trio_asprintf(&stmt,
+ "select notifid from notif_registrations where notifid='%|Ss'", nid_s);
+ ret = edg_wll_ExecStmt(ctx, stmt, NULL);
+ if ( ret == 0 )
+ edg_wll_SetError(ctx, ENOENT, "Unknown notification ID");
+ else if ( ret > 0 )
+ edg_wll_SetError(ctx, EPERM, "Only owner could access the notification");
+ }
+
+cleanup:
+ if ( !edg_wll_Error(ctx, NULL, NULL) && owner )
+ *owner = user;
+ else
+ free(user);
+ if ( nid_s ) free(nid_s);
+ if ( stmt ) free(stmt);
+
+ return edg_wll_Error(ctx, NULL, NULL);
+}
+
+
+ /* Format conditions
+ * - first of all separate all jobids
+ * - then format new condition list without jobids and encode it into an XML string
+ */
+static int split_cond_list(
+ edg_wll_Context ctx,
+ edg_wll_QueryRec const * const *conditions,
+ edg_wll_QueryRec ***nconds_out,
+ char ***jobs_out)
+{
+ edg_wll_QueryRec **nconds = NULL;
+ char **jobs = NULL;
+ int i, j, jobs_ct, nconds_ct;
+
+
+ if ( !conditions || !conditions[0] )
+ return edg_wll_SetError(ctx, EINVAL, "Empty condition list");
+
+ for ( nconds_ct = jobs_ct = i = 0; conditions[i]; i++ )
+ {
+ if ( conditions[i][0].attr && conditions[i][0].attr != EDG_WLL_QUERY_ATTR_JOBID )
+ nconds_ct++;
+ for ( j = 0; conditions[i][j].attr; j++ )
+ if ( conditions[i][j].attr == EDG_WLL_QUERY_ATTR_JOBID )
+ jobs_ct++;
+ }
+
+ if ( jobs_out && jobs_ct )
+ if ( !(jobs = calloc(jobs_ct+1, sizeof(char *))) )
+ {
+ edg_wll_SetError(ctx, errno, NULL);
+ goto cleanup;
+ }
+
+ if ( nconds_out && nconds_ct )
+ if ( !(nconds = calloc(nconds_ct+1, sizeof(edg_wll_QueryRec *))) )
+ {
+ edg_wll_SetError(ctx, errno, NULL);
+ goto cleanup;
+ }
+
+ if ( jobs ) for ( jobs_ct = i = 0; conditions[i]; i++ )
+ for ( j = 0; conditions[i][j].attr; j++ )
+ if ( conditions[i][j].attr == EDG_WLL_QUERY_ATTR_JOBID )
+ if ( !(jobs[jobs_ct++] = edg_wlc_JobIdGetUnique(conditions[i][j].value.j)) )
+ {
+ edg_wll_SetError(ctx, errno, NULL);
+ goto cleanup;
+ }
+
+ if ( nconds ) for ( nconds_ct = i = 0; conditions[i]; i++ )
+ if ( conditions[i][0].attr && conditions[i][0].attr != EDG_WLL_QUERY_ATTR_JOBID )
+ /* !!! DO NOT DEALLOCATE this arrays (it is not neccessary to allocate new
+ * mem - it's used only once and only for xml parsing
+ */
+ nconds[nconds_ct++] = (edg_wll_QueryRec *) (conditions[i]);
+
+ if ( jobs_out ) { *jobs_out = jobs; jobs = NULL; }
+ if ( nconds_out ) { *nconds_out = nconds; nconds = NULL; }
+
+cleanup:
+ if ( nconds ) free(nconds);
+ if ( jobs )
+ {
+ for ( i = 0; jobs[i]; i++ )
+ free(jobs[i]);
+ free(jobs);
+ }
+
+ return edg_wll_Error(ctx, NULL, NULL);
+}
+
+
+static int update_notif(
+ edg_wll_Context ctx,
+ const edg_wll_NotifId nid,
+ const char *conds,
+ const char *dest,
+ const char *valid)
+{
+ char *nid_s = NULL,
+ *stmt, *aux;
+ int ret;
+
+
+ if ( !(nid_s = edg_wll_NotifIdGetUnique(nid)) )
+ goto cleanup;
+
/* Format SQL update string
* (Only the owner could update the notification registration)
*/
- stmt = strdup("update notif_registrations set");
+ if ( !(stmt = strdup("update notif_registrations set")) )
+ {
+ edg_wll_SetError(ctx, errno, "updating notification records");
+ goto cleanup;
+ }
if ( dest )
{
trio_asprintf(&aux, "%s destination='%|Ss'", stmt, dest);
}
if ( conds )
{
- trio_asprintf(&aux, "%s %sconditions='%|Ss'",
+ trio_asprintf(&aux, "%s %sconditions='<and>%|Ss</and>'",
stmt, (dest||valid)? ",": "", conds);
free(stmt);
stmt = aux;
}
- trio_asprintf(&aux, "%s where notifid='%|Ss' and userid='%|Ss'",
- stmt, nid_s, owner);
+ trio_asprintf(&aux, "%s where notifid='%|Ss'", stmt, nid_s);
free(stmt);
stmt = aux;
ret = edg_wll_ExecStmt(ctx, stmt, NULL);
if ( ret == 0 )
edg_wll_SetError(ctx, ENOENT, "Unknown notification ID");
+ /*
+ * XXX: Be happy?
+ * May be: Rows matched: 1 Changed: 0 Warnings: 0 :-)
else if ( ret > 0 )
edg_wll_SetError(ctx, EPERM, "Updating notification records");
+ */
}
cleanup:
- if ( owner ) free(owner);
if ( nid_s ) free(nid_s);
if ( stmt ) free(stmt);
return edg_wll_Error(ctx, NULL, NULL);
}
+
+