Logo Search packages:      
Sourcecode: jabberd14 version File versions  Download package

result xdb_file_phandler ( instance  i,
dpacket  p,
void *  arg 
)

handle packets (request) we get from the XML router inside of jabberd

This function is the heart of xdb_file. It gets the requests of jabberd14, processes them, and sends replies

Parameters:
i the instance data of this instance of the component
p the dpacket that contains the request
arg xdb_file internal data of this instance of xdb::file (type is xdbf)
Returns:
r_DONE if the request has been handled, r_ERR on failure

Definition at line 285 of file xdb_file.cc.

References xdbf_struct::cache, deliver(), dpacket_new(), dpacket_struct::host, dpacket_struct::id, j_strcmp(), j_strlen(), log_notice(), log_warn(), xmlnode_list_item_t::next, xmlnode_list_item_t::node, dpacket_struct::p, xdbf_struct::sizelimit, xdbf_struct::spool, xdbf_struct::std_ns_prefixes, xdbf_struct::timeout, xdbf_struct::use_hashspool, dpacket_struct::x, xdb_file_full(), xdb_file_load(), xhash_free(), xhash_from_xml(), xhash_zap(), xmlnode2file_limited(), xmlnode_free(), xmlnode_get_attrib(), xmlnode_get_attrib_ns(), xmlnode_get_data(), xmlnode_get_firstchild(), xmlnode_get_list_item(), xmlnode_get_tag(), xmlnode_get_tags(), xmlnode_hide(), xmlnode_hide_attrib_ns(), xmlnode_insert_tag_node(), xmlnode_insert_tag_ns(), xmlnode_put_attrib_ns(), xmlnode_serialize_string(), and xmlnode_str().

Referenced by xdb_file().

                                                           {
    char *full, *ns, *act, *match;
    char *matchpath = NULL;
    char *matchns = NULL;
    xdbf xf = (xdbf)arg;
    xmlnode file, top, data;
    int ret = 0, flag_set = 0;

    log_debug2(ZONE, LOGT_STORAGE|LOGT_DELIVER, "handling xdb request %s", xmlnode_serialize_string(p->x, xmppd::ns_decl_list(), 0));

    /* the request needs to have a defined namespace, that it is querying */
    if ((ns = xmlnode_get_attrib_ns(p->x, "ns", NULL)) == NULL)
        return r_ERR;

    /* is it a get or a set request? */
    if (j_strcmp(xmlnode_get_attrib_ns(p->x, "type", NULL), "set") == 0)
        flag_set = 1;

    /* create the filename of the responsible file */
    /* is this request specific to a user or global data? */
    if (p->id->user != NULL)
        full = xdb_file_full(flag_set, p->p, xf->spool, p->id->server, p->id->user, "xml", xf->use_hashspool);
    else
      /* global data, not data for a user: never put it inside the hash directories (use global.xdb file) */
        full = xdb_file_full(flag_set, p->p, xf->spool, p->id->server, "global", "xdb", 0);

    /* no filename? -> error */
    if (full == NULL)
        return r_ERR;

    /* load the data from disk/cache */
    top = file = xdb_file_load(p->host, full, xf->cache);

    /* if we're dealing w/ a resource, just get that element <res id='resource'/> inside <xdb/> */
    if (p->id->resource != NULL) {
      top = xmlnode_get_list_item(xmlnode_get_tags(top, spools(p->p, "res[@id='", p->id->resource, "']", p->p), xf->std_ns_prefixes), 0);
      if (top == NULL) {
            top = xmlnode_insert_tag_ns(file, "res", NULL, NS_JABBERD_XDB);
            xmlnode_put_attrib_ns(top, "id", NULL, NULL, p->id->resource);
        }
    }

    /* just query the relevant namespace */
    data = xmlnode_get_list_item(xmlnode_get_tags(top, spools(p->p, "*[@xdbns='", ns, "']", p->p), xf->std_ns_prefixes), 0);

    if (flag_set) {
      act = xmlnode_get_attrib_ns(p->x, "action", NULL);
      match = xmlnode_get_attrib_ns(p->x, "match", NULL);
      matchpath = xmlnode_get_attrib_ns(p->x, "matchpath", NULL);
      matchns = xmlnode_get_attrib_ns(p->x, "matchns", NULL);
        if (act != NULL) {
          xht namespaces = NULL;

          if (matchns != NULL) {
            xmlnode namespacesxml = NULL;
            namespacesxml = xmlnode_str(matchns, j_strlen(matchns));
            namespaces = xhash_from_xml(namespacesxml);
            xmlnode_free(namespacesxml);
          }
            switch (*act) {
            case 'i': /* insert action */
                if (data == NULL) {
                  /* we're inserting into something that doesn't exist?!?!? */
                  data = xmlnode_insert_tag_ns(top, "foo", NULL, ns);
                  xmlnode_put_attrib_ns(data, "xdbns", NULL, NULL, ns);
                }
                if (matchpath != NULL) {
                  xmlnode_list_item match_item = NULL;

                  for (match_item = xmlnode_get_tags(data, matchpath, namespaces); match_item != NULL; match_item = match_item->next) {
                      xmlnode_hide(match_item->node);
                  }
                } else {
                  xmlnode_hide(xmlnode_get_tag(data, match)); /* any match is a goner */
                }
                /* insert the new chunk into the existing data */
                xmlnode_insert_tag_node(data, xmlnode_get_firstchild(p->x));
                break;
            case 'c': /* check action */
                if (matchpath != NULL) {
                  data = xmlnode_get_list_item(xmlnode_get_tags(data, matchpath, namespaces), 0);
                } else if(match != NULL) {
                  data = xmlnode_get_tag(data, match);
                }
                if(j_strcmp(xmlnode_get_data(data),xmlnode_get_data(xmlnode_get_firstchild(p->x))) != 0) {
                  log_debug2(ZONE, LOGT_STORAGE|LOGT_DELIVER, "xdb check action returning error to signify unsuccessful check");
                  if (namespaces)
                      xhash_free(namespaces);
                  return r_ERR;
                }
                flag_set = 0;

                /*
                 * XXX Is there a bug here?
                 *
                 * I suspect that the check action will always return r_ERR!
                 * Up to this point the ret variable has not been changed, and if
                 * we arrived here I cannot imagine how it should be changed afterwards.
                 * This means that the function will return r_ERR too.
                 * I expect this is a bug and something like "ret = 1;" should be inserted
                 * at this point.
                 *
                 * The problem is that I am not completely sure what the check action is
                 * supposed to do. What I imagine is:
                 * It is intended to compare the content of xdb with the content of the
                 * xdb request and return r_ERR if it is different and r_DONE if it
                 * is the same.
                 *
                 * It is only used in jsm/modules/mod_auth_plain.c in the function
                 * mod_auth_plain_jane(...) function. At this function there is already
                 * a check if the password is the same some lines above ... so it
                 * would make no sence to call the check action if it does what I said
                 * above as it would be always result in being different - in which
                 * case it is no surprize that we have no problem, that this function
                 * always returns r_ERR (which would signal that it's different too).
                 *
                 * It should be checked if the xdb_act(...) in mod_auth_plain_jane(...)
                 * is needed. If it isn't, we could remove the check action from
                 * xdb completely.
                 *
                 * Please see also:
                 * http://web.archive.org/web/20020601233959/http://jabberd.jabberstudio.org/1.4/142changelog.html
                 * In that case it seems to be a bug here ...
                 */
                break;
            default:
                log_warn(p->host, "unable to handle unknown xdb action '%s'", act);
                return r_ERR;
            }
          if (namespaces)
            xhash_free(namespaces);
        } else {
            if (data != NULL)
                xmlnode_hide(data);

            /* copy the new data into file */
            data = xmlnode_insert_tag_node(top, xmlnode_get_firstchild(p->x));
            xmlnode_put_attrib_ns(data, "xdbns", NULL, NULL, ns);
        }

        /* save the file if we still want to */
      if (flag_set) {
          int tmp = xmlnode2file_limited(full,file,xf->sizelimit);
          if (tmp == 0)
            log_notice(p->id->server,"xdb request failed, due to the size limit of %i to file %s", xf->sizelimit, full);
          else if (tmp < 0)
            log_error(p->id->server,"xdb request failed, unable to save to file %s",full);
          else
            ret = 1;
      }
    } else {
        /* a get always returns, data or not */
        ret = 1;

        if (data != NULL) {
          /* cool, send em back a copy of the data */
            xmlnode_hide_attrib_ns(xmlnode_insert_tag_node(p->x, data), "xdbns", NULL);
        }
    }

    if (ret) {
        xmlnode_put_attrib_ns(p->x, "type", NULL, NULL, "result");
        xmlnode_put_attrib_ns(p->x, "to", NULL, NULL, xmlnode_get_attrib(p->x,"from"));
        xmlnode_put_attrib_ns(p->x, "from", NULL, NULL, jid_full(p->id));
        deliver(dpacket_new(p->x), NULL); /* dpacket_new() shouldn't ever return NULL */

        /* remove the cache'd item if it was a set or we're not configured to cache */
        if (xf->timeout == 0 || flag_set) {
            log_debug2(ZONE, LOGT_STORAGE, "decaching %s",full);
            xhash_zap(xf->cache,full);
            xmlnode_free(file);
        }
        return r_DONE;
    } else {
        return r_ERR;
    }
}


Generated by  Doxygen 1.6.0   Back to index