util.c   [plain text]


/* --------------------------------------------------------------------------
 *
 * License
 *
 * The contents of this file are subject to the Jabber Open Source License
 * Version 1.0 (the "JOSL").  You may not copy or use this file, in either
 * source code or executable form, except in compliance with the JOSL. You
 * may obtain a copy of the JOSL at http://www.jabber.org/ or at
 * http://www.opensource.org/.  
 *
 * Software distributed under the JOSL is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the JOSL
 * for the specific language governing rights and limitations under the
 * JOSL.
 *
 * Copyrights
 * 
 * Portions created by or assigned to Jabber.com, Inc. are 
 * Copyright (c) 1999-2002 Jabber.com, Inc.  All Rights Reserved.  Contact
 * information for Jabber.com, Inc. is available at http://www.jabber.com/.
 *
 * Portions Copyright (c) 1998-1999 Jeremie Miller.
 * 
 * Acknowledgements
 * 
 * Special thanks to the Jabber Open Source Contributors for their
 * suggestions and support of Jabber.
 * 
 * Alternatively, the contents of this file may be used under the terms of the
 * GNU General Public License Version 2 or later (the "GPL"), in which case
 * the provisions of the GPL are applicable instead of those above.  If you
 * wish to allow use of your version of this file only under the terms of the
 * GPL and not to allow others to use your version of this file under the JOSL,
 * indicate your decision by deleting the provisions above and replace them
 * with the notice and other provisions required by the GPL.  If you do not
 * delete the provisions above, a recipient may use your version of this file
 * under either the JOSL or the GPL. 
 * 
 *
 * util.c -- utility functions for jsm
 * 
 * --------------------------------------------------------------------------*/

#include "jsm.h"

/*
 *  js_bounce -- short_desc
 *  
 *  Long_description
 *
 *  parameters
 *  	x -- the node to bounce
 *      terr - the error code describing the reason for the bounce
 *
 */
void js_bounce(jsmi si, xmlnode x, terror terr)
{
    /* if the node is a subscription */
    if(j_strcmp(xmlnode_get_name(x),"presence") == 0 && j_strcmp(xmlnode_get_attrib(x,"type"),"subscribe") == 0)
    {
        /* turn the node into a result tag. it's a hack, but it get's the job done */
        jutil_iqresult(x);
        xmlnode_put_attrib(x,"type","unsubscribed");
        xmlnode_insert_cdata(xmlnode_insert_tag(x,"status"),terr.msg,-1);

        /* deliver it back to the client */
        js_deliver(si, jpacket_new(x));
        return;

    }

    /* if it's a presence packet, just drop it */
    if(j_strcmp(xmlnode_get_name(x),"presence") == 0 || j_strcmp(xmlnode_get_attrib(x,"type"),"error") == 0)
    {
        log_debug(ZONE,"dropping %d packet %s",terr.code,xmlnode2str(x));
        xmlnode_free(x);
        return;
    }

    /* if it's neither of these, make an error message an deliver it */
    jutil_error(x, terr);
    js_deliver(si, jpacket_new(x));

}


/*
 *  js_config -- get a configuration node
 *
 *  parameters
 *      si -- session instance
 *      query -- the path through the tag hierarchy of the desired tag
 *               eg. for the conf file <foo><bar>bar value</bar><baz/><foo>
 *               use "foo/bar" to retreive the bar node
 *
 *  returns
 *      a pointer to the xmlnode specified in query
 *      or the root config node if query is null
 */
xmlnode js_config(jsmi si, char *query)
{

    log_debug(ZONE,"config query %s",query);

    if(query == NULL)
        return si->config;
    else
        return xmlnode_get_tag(si->config, query);
}

/* macro to make sure the jid is a local user */
int js_islocal(jsmi si, jid id)
{
    if(id == NULL || id->user == NULL) return 0;
    if(ghash_get(si->hosts, id->server) == NULL) return 0;
    return 1;
}

/* macro to validate a user as an admin */
int js_admin(udata u, int flag)
{
    if(u == NULL || u->admin == ADMIN_NONE) return 0;

    if(u->admin == ADMIN_UNKNOWN)
    {
        if(js_config(u->si, spools(u->p,"admin/write=",jid_full(u->id),u->p)) != NULL)
        {
            u->admin = ADMIN_READ | ADMIN_WRITE;
        }else if(js_config(u->si, spools(u->p,"admin/read=",jid_full(u->id),u->p)) != NULL){
            u->admin = ADMIN_READ;
        }else{
            u->admin = ADMIN_NONE;
        }
    }

    if(u->admin & flag)
        return 1;

    return 0;
}


jid js_trustees(udata u)
{
    xmlnode roster, cur;

    if(u == NULL) return NULL;

    if(u->utrust != NULL) return u->utrust;

    log_debug(ZONE,"generating trustees list for user %s",jid_full(u->id));

    /* initialize with at least self */
    u->utrust = jid_user(u->id);

    /* fill in rest from roster */
    roster = xdb_get(u->si->xc, u->id, NS_ROSTER);
    for(cur = xmlnode_get_firstchild(roster); cur != NULL; cur = xmlnode_get_nextsibling(cur))
    {
        if(j_strcmp(xmlnode_get_attrib(cur,"subscription"),"from") == 0 || j_strcmp(xmlnode_get_attrib(cur,"subscription"),"both") == 0)
            jid_append(u->utrust,jid_new(u->p,xmlnode_get_attrib(cur,"jid")));
    }
    xmlnode_free(roster);

    return u->utrust;
}


/* this tries to be a smarter jid matcher, where a "host" matches any "user@host" and "user@host" matches "user@host/resource" */
int _js_jidscanner(jid id, jid match)
{
    for(;id != NULL; id = id->next)
    {
        if(j_strcmp(id->server,match->server) != 0) continue;
        if(id->user == NULL) return 1;
        if(j_strcasecmp(id->user,match->user) != 0) continue;
        if(id->resource == NULL) return 1;
        if(j_strcmp(id->resource,match->resource) != 0) continue;
        return 1;
    }
    return 0;
}

/* returns true if id is trusted for this user */
int js_trust(udata u, jid id)
{
    if(u == NULL || id == NULL) return 0;

    /* first, check global trusted ids */
    if(_js_jidscanner(u->si->gtrust,id)) return 1;

    /* then check user trusted ids */
    if(_js_jidscanner(js_trustees(u),id)) return 1;

    return 0;
}


/* returns true if this mapi call is for the "online" event, sucks, should just rewrite the whole mapi to make things like this better */
int js_online(mapi m)
{
    if(m == NULL || m->packet == NULL || m->packet->to != NULL || m->s == NULL || m->s->priority >= 0) return 0;

    if(jpacket_subtype(m->packet) == JPACKET__AVAILABLE || jpacket_subtype(m->packet) == JPACKET__INVISIBLE) return 1;

    return 0;
}